MVP簡介
相信大家對 MVC 都是比較熟悉了:M-Model-模型、V-View-視圖、C-Controller-控制器,MVP作為MVC的演化版本,也是作為用戶界面(用戶層)的實現模式,那么類似的MVP所對應的意義:M-Model-模型、V-View-視圖、P-Presenter-表示器。
MVC詳見博客: Android之MVC模式的使用
Model
Model 是用戶界面需要顯示數據的抽象,也可以理解為從業務數據(結果)那里到用戶界面的抽象。
View
視圖這一層體現的很輕薄,負責顯示數據、提供友好界面跟用戶交互就行。MVP下Activity和Fragment體現在了這一層,Activity一般也就做加載UI視圖、設置監聽再交由Presenter處理的一些工作,所以也就需要持有相應Presenter的引用。
Presenter
Presenter這一層處理着程序各種邏輯的分發,收到View層UI上的反饋命令、定時命令、系統命令等指令后分發處理邏輯交由業務層做具體的業務操作,然后將得到的 Model 給 View 顯示。
MVC和MVP的區別
在 MVC 中:
- View 可以與 Model 直接交互;
- Controller 可以被多個 View 共享;
- Controller 可以決定顯示哪個 View 。
在 MVP 中:
- View 不直接與 Model 交互;
- Presenter 與 View 通過接口來交互,更有利於添加單元測試;
- 通常 View 與 Presenter 是一對一的,但復雜的 View 可能綁定多個 Presenter 來處理;
- Presenter 也可以直接進行 View 上的渲染。
模仿登錄案例:(demo中包含登錄和網絡數據請求)
model
public class ModelSignIn implements ILoginSignIn { @Override public void onSignIn(String name, String pwd, IOnSetListenter listenter) { if (name.isEmpty()) { if (listenter!=null) { listenter.onError("輸入用戶名為空"); return; } } if (pwd.isEmpty()) { if (listenter!=null) { listenter.onError("輸入密碼為空"); return; } } if(name.equals("dickyqie") && pwd.equals("123456")) { if (listenter!=null) { listenter.onError("登錄成功"); return; } }else{ if (listenter!=null) { listenter.onError("登錄失敗"); return; } } } }
presenter
public class Presenter extends BasePresenter<IView> { ILoginSignIn iLoginSignIn=new ModelSignIn(); public void setSignIn(String name,String pwd) { iLoginSignIn.onSignIn(name, pwd, new ILoginSignIn.IOnSetListenter() { IView view=getView(); @Override public void onError(String error) { if(view!=null){ view.showToast(error); } } @Override public void onSccess(String repsonce) { if(view!=null){ view.showToast(repsonce); } } }); } }
activity
public class MainActivity extends BaseActivity<IView,Presenter> implements IView,View.OnClickListener{ EditText username; EditText password; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { username=(EditText)findViewById(R.id.username); password=(EditText)findViewById(R.id.password); findViewById(R.id.login).setOnClickListener(this); } @Override public Presenter createPersenter() { return new Presenter(); } @Override public void onClick(View v) { String name=username.getText().toString(); String pwd=password.getText().toString(); p.setSignIn(name,pwd); } @Override public void showToast(String msg) { Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_LONG).show(); } }
網絡請求
public class MainActivity extends BaseActivity<IView,Presenter> implements IView,View.OnClickListener { private TextView textView; private ProgessDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView(){ textView=(TextView) findViewById(R.id.text); findViewById(R.id.btn).setOnClickListener(this); } @Override public void onLoadContributorStart() { showProgress(); } @Override public void onLoadContribtorComplete(String topContributor) { //得到主線程的數據 Message msg=new Message(); msg.what=1; msg.obj=topContributor; handler.sendMessage(msg); } Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); dismissProgress(); textView.setText(msg.obj.toString()); } }; @Override public void onClick(View v) { p.setGet(); } @Override public Presenter createPresenter() { return new Presenter(); } @Override public void onNetWork() { Toast.makeText(getApplicationContext(),"網絡未連接",Toast.LENGTH_LONG).show(); } @Override public void onError() { Toast.makeText(getApplicationContext(),"數據加載失敗",Toast.LENGTH_LONG).show(); textView.setText(""); } /*** * 啟動 */ public void showProgress() { if(dialog==null) { dialog=new ProgessDialog(MainActivity.this); } dialog.showMessage("正在加載"); } /*** * 關閉 */ public void dismissProgress() { if(dialog==null) { dialog=new ProgessDialog(this); } dialog.dismiss(); } }
不要忘記在AndroidManifest.xml加權限哦!
<uses-permission android:name="android.permission.INTERNET"/>
由於代碼太多,完整代碼未給出,源碼直接下載即可
源代碼下載:https://github.com/DickyQie/android-development-model