本文分析的源碼是開源項目實例,參考地址:https://github.com/antoniolg/androidmvpjava
以最熟悉的login登陸頁面爲例,目錄結構以下:node
其中包含3個interface,3個實現,兩兩一組。android
【LogView接口源碼】git
1 public interface LoginView { 2 void showProgress(); 3 4 void hideProgress(); 5 6 void setUsernameError(); 7 8 void setPasswordError(); 9 10 void navigateToHome(); 11 }
【LoginActivity.java源碼】github
1 public class LoginActivity extends Activity implements LoginView, View.OnClickListener { 2 3 private ProgressBar progressBar; 4 private EditText username; 5 private EditText password; 6 private LoginPresenter presenter; //持有presenter對象 7 8 @Override protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_login); 11 12 progressBar = (ProgressBar) findViewById(R.id.progress); 13 username = (EditText) findViewById(R.id.username); 14 password = (EditText) findViewById(R.id.password); 15 findViewById(R.id.button).setOnClickListener(this); 16 17 presenter = new LoginPresenterImpl(this,new LoginInteractorImpl()); //new一個代理對象:LoginPresenter 18 } 19 20 @Override protected void onDestroy() { 21 presenter.onDestroy(); 22 super.onDestroy(); 23 } 24 25 @Override public void showProgress() { 26 progressBar.setVisibility(View.VISIBLE); 27 } 28 29 @Override public void hideProgress() { 30 progressBar.setVisibility(View.GONE); 31 } 32 33 @Override public void setUsernameError() { 34 username.setError(getString(R.string.username_error)); 35 } 36 37 @Override public void setPasswordError() { 38 password.setError(getString(R.string.password_error)); 39 } 40 41 @Override public void navigateToHome() { 42 startActivity(new Intent(this, MainActivity.class)); 43 finish(); 44 } 45 46 @Override public void onClick(View v) { 47 presenter.validateCredentials(username.getText().toString(), password.getText().toString()); 48 } 49 }
【說明】網絡
【1】實現了 LoginView 接口,架構
【2】持有presenter對象,而且new了一個presenter的實現類對象。ide
1 private LoginPresenter presenter; //持有presenter對象
1 presenter = new LoginPresenterImpl(this,new LoginInteractorImpl()); //new一個代理對象:LoginPresenter
【3】在動做 觸發的時候,調用了代理validateCredentials方法post
1 /** 2 * 觸發調用代理的方法 3 * @param v 4 */ 5 @Override public void onClick(View v) { 6 presenter.validateCredentials(username.getText().toString(), password.getText().toString()); 7 }
一樣在onDestroy()中引用了presenter代理實現的方法this
1 @Override protected void onDestroy() { 2 presenter.onDestroy(); 3 super.onDestroy(); 4 }
【LoginPresenter源碼】須要時兩個被view調用的方法
1 public interface LoginPresenter { 2 3 void validateCredentials(String username, String password); 4 5 void onDestroy(); 6 }
【LoginPresenterImpl】代理的實現類:
1 public class LoginPresenterImpl implements LoginPresenter, LoginInteractor.OnLoginFinishedListener { 2 3 private LoginView loginView; //持有view的對象 4 private LoginInteractor loginInteractor; //持有model對象 5 6 public LoginPresenterImpl(LoginView loginView, LoginInteractor loginInteractor) { 7 this.loginView = loginView; //在構造方法中將view傳遞進來 8 this.loginInteractor = loginInteractor; //在構造方法中將model傳遞進來 9 } 10 11 /** 12 * 在執行登陸驗證的動做: 13 * 【1】觸發view的動做 14 * 【2】將參數傳遞給model 15 * @param username 16 * @param password 17 */ 18 @Override public void validateCredentials(String username, String password) { 19 if (loginView != null) { 20 loginView.showProgress(); 21 } 22 23 loginInteractor.login(username, password, this); 24 } 25 26 @Override public void onDestroy() { 27 loginView = null; 28 } 29 30 @Override public void onUsernameError() { 31 if (loginView != null) { 32 loginView.setUsernameError(); 33 loginView.hideProgress(); 34 } 35 } 36 37 @Override public void onPasswordError() { 38 if (loginView != null) { 39 loginView.setPasswordError(); 40 loginView.hideProgress(); 41 } 42 } 43 44 @Override public void onSuccess() { 45 if (loginView != null) { 46 loginView.navigateToHome(); 47 } 48 } 49 }
【model接口】
1 public interface LoginInteractor { 2 3 interface OnLoginFinishedListener { //被presenter實現的接口 4 void onUsernameError(); 5 void onPasswordError(); 6 void onSuccess(); 7 } 8 9 void login(String username, String password, OnLoginFinishedListener listener); 10 11 }
【1】 Presenter代理實現類:實現了LoginPresenter,還實現了model接口的中的LoginInteractor.OnLoginFinishedListener接口。
【2】在代理類中持有了構造方法中直接傳遞進去了View和Model對象。
1 private LoginView loginView; //持有view的接口對象 2 private LoginInteractor loginInteractor; //持有model接口對象 3 4 public LoginPresenterImpl(LoginView loginView, LoginInteractor loginInteractor) { 5 this.loginView = loginView; //在構造方法中將view傳遞進來 6 this.loginInteractor = loginInteractor; //在構造方法中將model傳遞進來 7 }
此處持有的是接口對象,在構造LoginPresenterImpl時,即在View中new代理類對象時:直接傳遞了本身自己和model實現類。對接口進行了轉化,將接口對象轉化爲了實現類(注意)。
1 presenter = new LoginPresenterImpl(this,new LoginInteractorImpl()); //new一個代理對象:LoginPresenter
【3】在動做執行時:直接調用了View的方法loginView.showProgress(),Model中對數據的傳遞和處理:loginInteractor.login(username, password, this)
1 /** 2 * 在執行登陸驗證的動做: 3 * 【1】觸發view的動做 4 * 【2】將參數傳遞給model 5 * @param username 6 * @param password 7 */ 8 @Override public void validateCredentials(String username, String password) { 9 if (loginView != null) { 10 loginView.showProgress(); 11 } 12 13 loginInteractor.login(username, password, this); //此處只是將數據傳遞給了model最終的對數據的處理是在model中完成的 14 }
【4】model接口的中的LoginInteractor.OnLoginFinishedListener接口主要是對Login控制,Model不一樣的處理的狀態經過Model接口,在Presenter調用來更新View的界面顯示。主要是對view的操做。
1 interface OnLoginFinishedListener { //回調狀態的更新View的UI顯示
2 void onUsernameError(); 3 void onPasswordError(); 4 void onSuccess(); 5 }
1 @Override public void onUsernameError() { 2 if (loginView != null) { 3 loginView.setUsernameError(); 4 loginView.hideProgress(); 5 } 6 } 7 8 @Override public void onPasswordError() { 9 if (loginView != null) { 10 loginView.setPasswordError(); 11 loginView.hideProgress(); 12 } 13 } 14 15 @Override public void onSuccess() { 16 if (loginView != null) { 17 loginView.navigateToHome(); 18 } 19 }
【接口】包含兩部分:①presenter實現的接口②Model 對數據處理的方法
1 public interface LoginInteractor { 2 3 interface OnLoginFinishedListener { //被presenter實現的接口 4 void onUsernameError(); 5 void onPasswordError(); 6 void onSuccess(); 7 } 8 9 //對view傳遞的數據的處理,此處參數有presenter實現的接口對象 OnLoginFinishedListener 10 void login(String username, String password, OnLoginFinishedListener listener); 11 12 }
【model實現】實現了LoginInteractor接口,只實現了login方法。
1 public class LoginInteractorImpl implements LoginInteractor { 2 3 @Override 4 public void login(final String username, final String password, final OnLoginFinishedListener listener) { 5 // Mock login. I'm creating a handler to delay the answer a couple of seconds 6 new Handler().postDelayed(new Runnable() { 7 @Override public void run() { 8 if (TextUtils.isEmpty(username)) { 9 listener.onUsernameError(); 10 return; 11 } 12 if (TextUtils.isEmpty(password)) { 13 listener.onPasswordError(); 14 return; 15 } 16 listener.onSuccess(); //最終的數據處理這裏作了臨時的處理,調用listener的方法;實際項目會對作網絡請求 17 } 18 }, 2000); 19 } 20 }
最終的數據處理這裏作了臨時的處理,調用LoginPresenterImpl中的onSuccess方法,是Model接口中的方法;實際項目會對作網絡請求
1 @Override public void onSuccess() { 2 if (loginView != null) { 3 loginView.navigateToHome(); 4 } 5 }
【view接口中的定義】
1 public interface LoginView {
2 void showProgress(); 3 4 void hideProgress(); 5 6 void setUsernameError(); 7 8 void setPasswordError(); 9 10 void navigateToHome(); //view的頁面的跳轉 11 }
1 public class LoginActivity extends Activity implements LoginView, View.OnClickListener { 2
3 private ProgressBar progressBar; 4 5 ...... 6 @Override public void navigateToHome() { 7 startActivity(new Intent(this, MainActivity.class)); //Activity的實現 跳轉到MainAcitivity頁面 8 finish(); 9 } 10 ......
【觸發跳轉】model的實現類進行了跳轉頁面的觸發
1 public class LoginInteractorImpl implements LoginInteractor {
2
3 @Override 4 public void login(final String username, final String password, final OnLoginFinishedListener listener) { 5 // Mock login. I'm creating a handler to delay the answer a couple of seconds 6 new Handler().postDelayed(new Runnable() { 7 @Override public void run() { 8 if (TextUtils.isEmpty(username)) { 9 listener.onUsernameError(); 10 return; 11 } 12 if (TextUtils.isEmpty(password)) { 13 listener.onPasswordError(); 14 return; 15 } 16 listener.onSuccess(); //觸發跳轉 17 } 18 }, 2000); 19 } 20 }
【代理類作中介】
1 public class LoginPresenterImpl implements LoginPresenter, LoginInteractor.OnLoginFinishedListener {
2 ...... 3 @Override public void onSuccess() { 4 if (loginView != null) { 5 loginView.navigateToHome(); //跳轉 6 } 7 } 8 ......
【總結】是一個反向的過程:model-->presenter-->view
調用過程總結以下:
數據的傳遞過程:
【View發起】LoginActivity
1 /** 2 * 觸發調用代理的方法 3 * @param v 4 */ 5 @Override public void onClick(View v) { 6 presenter.validateCredentials(username.getText().toString(), password.getText().toString()); 7 }
【Presenter傳遞】LoginPresenterImpl中調用model中的方法進行處理
1 /** 2 * 在執行登陸驗證的動做: 3 * 【1】觸發view的動做 4 * 【2】將參數傳遞給model 5 * @param username 6 * @param password 7 */ 8 @Override public void validateCredentials(String username, String password) { 9 if (loginView != null) { 10 loginView.showProgress(); 11 } 12 13 loginInteractor.login(username, password, this); 14 }
【Model的處理】LoginInteractorImpl 的login方法中處理
1 public class LoginInteractorImpl implements LoginInteractor { 2 3 @Override 4 public void login(final String username, final String password, final OnLoginFinishedListener listener) { 5 // Mock login. I'm creating a handler to delay the answer a couple of seconds 6 new Handler().postDelayed(new Runnable() { 7 @Override public void run() { 8 if (TextUtils.isEmpty(username)) { 9 listener.onUsernameError(); 10 return; 11 } 12 if (TextUtils.isEmpty(password)) { 13 listener.onPasswordError(); 14 return; 15 } 16 listener.onSuccess(); //最終的數據處理這裏作了臨時的處理,調用listener的方法;實際項目會對作網絡請求 17 } 18 }, 2000); 19 } 20 }
【關鍵】關鍵是接口當中的方法的定義。
【接口總結】
【View的接口】
【1】將Activity與UI相關的動做所有暴露給Presenter,只負責更新UI。
【2】 由於View只負責更新UI,具體更新的時機由Prsenter直接決定,Model經過調用接口間接決定。Model調用的接口是:OnLoginFinishedListener,即被Prsenter的實現的Model的接口。
1 public interface LoginView { 2 void showProgress(); 3 4 void hideProgress(); 5 6 void setUsernameError(); 7 8 void setPasswordError(); 9 10 void navigateToHome(); //view的頁面的跳轉 11 }
【Presenter接口】
1 public interface LoginPresenter { 2 3 void validateCredentials(String username, String password); 4 5 void onDestroy(); 6 }
【1】包含數據參數的傳遞validateCredentials(String username, String password),View調用,經過Presenter中轉,最終傳遞給Model處理。
1 /** 2 * 觸發調用代理的方法 3 * @param v 4 */ 5 @Override public void onClick(View v) { //在Acitivity中的調用
6 presenter.validateCredentials(username.getText().toString(), password.getText().toString()); }
1 /** 2 * 在執行登陸驗證的動做: 3 * 【1】觸發view的動做 4 * 【2】將參數傳遞給model 5 * @param username 6 * @param password 7 */ 8 @Override public void validateCredentials(String username, String password) { //Presenter代理的實現 9 if (loginView != null) { 10 loginView.showProgress(); 11 } 12 13 loginInteractor.login(username, password, this); 14 }
【2】onDestory()在Presenter中對View接口對象置空,等待gc。在Acitivity的OnDestory生命週期中調用此方法,釋放view對象。
1 @Override public void onDestroy() { //Presenter代理的實現 2 loginView = null; 3 }
1 @Override protected void onDestroy() { //在Acitivity生命週期中的調用 2 presenter.onDestroy(); 3 super.onDestroy(); 4 }
【Model接口】兩部分:
1 public interface LoginInteractor { 2 3 interface OnLoginFinishedListener { //被presenter實現的接口 4 void onUsernameError(); 5 void onPasswordError(); 6 void onSuccess(); 7 } 8 9 //對view傳遞的數據的處理,此處參數有presenter實現的接口對象 OnLoginFinishedListener 10 void login(String username, String password, OnLoginFinishedListener listener); 11 12 }
【部分1】被Presenter實現的接口OnLoginFinishedListener ,是Presenter代理暴露出來的狀態,對應於View的UI的更新。
1 @Override public void onUsernameError() { //Presenter代理的實現 2 if (loginView != null) { 3 loginView.setUsernameError(); 4 loginView.hideProgress(); 5 } 6 } 7 8 @Override public void onPasswordError() { //Presenter代理的實現 9 if (loginView != null) { 10 loginView.setPasswordError(); 11 loginView.hideProgress(); 12 } 13 } 14 15 @Override public void onSuccess() { //Presenter代理的實現 16 if (loginView != null) { 17 loginView.navigateToHome(); 18 } 19 }
【部分2】對Acitivity傳遞過來的數據的處理。注意:其中將presenter實現的接口對象 OnLoginFinishedListener做爲參數傳遞給了此方法,最終用來根據對數據處理的不一樣的結果回調activity的UI更新。
1 //對view傳遞的數據的處理,此處參數有presenter實現的接口對象 OnLoginFinishedListener 2 void login(String username, String password, OnLoginFinishedListener listener);
1 /** 2 * 在執行登陸驗證的動做: 3 * 【1】觸發view的動做 4 * 【2】將參數傳遞給model 5 * @param username 6 * @param password 7 */ 8 @Override public void validateCredentials(String username, String password) { 9 if (loginView != null) { 10 loginView.showProgress(); 11 } 12 13 loginInteractor.login(username, password, this); //Presenter代理的調用 14 }
1 public class LoginInteractorImpl implements LoginInteractor { //Model中的實現 2 3 @Override 4 public void login(final String username, final String password, final OnLoginFinishedListener listener) { 5 // Mock login. I'm creating a handler to delay the answer a couple of seconds 6 new Handler().postDelayed(new Runnable() { 7 @Override public void run() { 8 if (TextUtils.isEmpty(username)) { 9 listener.onUsernameError(); 10 return; 11 } 12 if (TextUtils.isEmpty(password)) { 13 listener.onPasswordError(); 14 return; 15 } 16 listener.onSuccess(); //最終的數據處理這裏作了臨時的處理,調用listener的方法;實際項目會對作網絡請求 17 } 18 }, 2000); 19 } 20 }
【功能】
【1】ListeView的數據設置
【2】item點擊事件
【說明】一樣也是三個接口,三個實現,兩兩一組
【view接口】
1 public interface MainView { 2 3 void showProgress(); 4 5 void hideProgress(); 6 7 void setItems(List<String> items); 8 9 void showMessage(String message); 10 }
【view實現】
1 public class MainActivity extends Activity implements MainView, AdapterView.OnItemClickListener { 2 3 private ListView listView; 4 private ProgressBar progressBar; 5 private MainPresenter presenter; //持有代理的對象 6 7 @Override protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 setContentView(R.layout.activity_main); 10 listView = (ListView) findViewById(R.id.list); 11 listView.setOnItemClickListener(this); 12 progressBar = (ProgressBar) findViewById(R.id.progress); 13 presenter = new MainPresenterImpl(this, new FindItemsInteractorImpl()); //生成代理,而且將model做爲參數傳遞 14 } 15 16 @Override protected void onResume() { 17 super.onResume(); 18 presenter.onResume(); 19 } 20 21 @Override protected void onDestroy() { 22 presenter.onDestroy(); 23 super.onDestroy(); 24 } 25 26 @Override public void showProgress() { 27 progressBar.setVisibility(View.VISIBLE); 28 listView.setVisibility(View.INVISIBLE); 29 } 30 31 @Override public void hideProgress() { 32 progressBar.setVisibility(View.INVISIBLE); 33 listView.setVisibility(View.VISIBLE); 34 } 35 36 @Override public void setItems(List<String> items) { 37 listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items)); 38 } 39 40 @Override public void showMessage(String message) { 41 Toast.makeText(this, message, Toast.LENGTH_LONG).show(); 42 } 43 44 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 45 presenter.onItemClicked(position); //觸發代理的item接口,將位置參數position傳遞 46 } 47 }
【1】持有代理接口對象,此處持有的是接口對象,在構造LoginPresenterImpl時,即在View中new代理類對象時:直接傳遞了本身自己和model實現類。對接口進行了轉化,將接口對象轉化爲了實現類(注意)。
1 ...... 2 private MainPresenter presenter; //持有代理接口的對象 3 ...... 4 presenter = new MainPresenterImpl(this, new FindItemsInteractorImpl()); //生成代理,而且將model做爲參數傳遞
【2】實現接口
1 @Override public void setItems(List<String> items) { 2 listView.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items)); //設置ListView的adpter 3 }
【3】觸發動做點擊動做
1 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //在listView的itemClick中觸發presenter的接口的參數的傳遞 2 presenter.onItemClicked(position); //觸發代理的item接口,將位置參數position傳遞 3 }
【代理的接口】
1 public interface MainPresenter { 2 3 void onResume(); 4 5 void onItemClicked(int position); 6 7 void onDestroy(); 8 }
在看代理的實現以前先看下Model接口:presenter實現了此接口OnFinishedListener
1 public interface FindItemsInteractor { 2 3 interface OnFinishedListener { //presenter實現了此接口 4 void onFinished(List<String> items); 5 } 6 7 void findItems(OnFinishedListener listener); 8 }
【代理接口的實現】
1 public class MainPresenterImpl implements MainPresenter, FindItemsInteractor.OnFinishedListener { 2 3 private MainView mainView; //持有view對象 4 private FindItemsInteractor findItemsInteractor; //持有model對象 5 6 /** 7 * 在構造方法中將view和presenter做爲參數傳遞進來 8 * @param mainView view對象 9 * @param findItemsInteractor model對象 10 */ 11 public MainPresenterImpl(MainView mainView, FindItemsInteractor findItemsInteractor) { 12 this.mainView = mainView; 13 this.findItemsInteractor = findItemsInteractor; 14 } 15 16 @Override public void onResume() { 17 if (mainView != null) { 18 mainView.showProgress(); 19 } 20 //對model中的 21 findItemsInteractor.findItems(this); 22 } 23 24 /** 25 * 代理對view的點擊事件的響應 26 * @param position 27 */ 28 @Override public void onItemClicked(int position) { 29 if (mainView != null) { 30 mainView.showMessage(String.format("Position %d clicked", position + 1)); 31 } 32 } 33 34 @Override public void onDestroy() { 35 mainView = null; 36 } 37 38 @Override public void onFinished(List<String> items) { 39 if (mainView != null) { 40 mainView.setItems(items); //將Model返回的數據在View中進行了設置 --List<String>是Model返回的數據 41 mainView.hideProgress(); 42 } 43 } 44 45 public MainView getMainView() { 46 return mainView; 47 } 48 }
代理主要完成下面的工做:
【1】在構造方法中持有view和model的對象
1 /** 2 * 在構造方法中將view和presenter做爲參數傳遞進來 3 * @param mainView view對象 4 * @param findItemsInteractor model對象 5 */ 6 public MainPresenterImpl(MainView mainView, FindItemsInteractor findItemsInteractor) { 7 this.mainView = mainView; 8 this.findItemsInteractor = findItemsInteractor; 9 }
【2】響應view的中Listview的itemClick的點擊事件,onItemClicked直接獲取位置position,經過Toast處理。
1 /** 2 * 代理對view的點擊事件的響應 3 * @param position 4 */ 5 @Override public void onItemClicked(int position) { 6 if (mainView != null) { 7 mainView.showMessage(String.format("Position %d clicked", position + 1)); 8 } 9 }
【3】在onFinished接口回調中取回Model生成的數據List<String>,而後再經過回調,設置給View的Iitems,最終是將Model中的數據傳給View,設置給ListView的Adapdter;
1 @Override public void onFinished(List<String> items) { 2 if (mainView != null) { 3 mainView.setItems(items); //將Model返回的數據在View中進行了設置 4 mainView.hideProgress(); 5 } 6 }
【4】發出請求給Model構造數據
1 @Override public void onResume() { 2 if (mainView != null) { 3 mainView.showProgress(); 4 } 5 //對model中的 6 findItemsInteractor.findItems(this); 7 }
【5】將View的接口對象置空。被Acitivity在OnDestory()調用。
1 @Override public void onDestroy() { //Presenter 實現 2 mainView = null; 3 }
1 @Override protected void onDestroy() { //在Acitivity中調用 2 presenter.onDestroy(); 3 super.onDestroy(); 4 }
【接口】findItems方法中持有OnFinishedListener 接口,由於model須要構造數據,將數據經過OnFinishedListener 中的onFinished(List<String> items)方法中的參數List<String>將數據回調傳遞給Presenter,而後傳遞給View,最終設置給View中的ListView的Adapter。
1 public interface FindItemsInteractor { 2 3 interface OnFinishedListener { //presenter實現了此接口 4 void onFinished(List<String> items); 5 } 6 7 void findItems(OnFinishedListener listener); 8 }
【Model接口的實現】
【1】createArrayList()對ListView的數據的構造
【2】接口OnFinishedListener的onFinished對 List<String>數據的回傳。
1 public class FindItemsInteractorImpl implements FindItemsInteractor { 2 @Override public void findItems(final OnFinishedListener listener) { 3 new Handler().postDelayed(new Runnable() { 4 @Override public void run() { 5 listener.onFinished(createArrayList()); 6 } 7 }, 2000); 8 } 9 10 private List<String> createArrayList() { 11 return Arrays.asList( 12 "Item 1", 13 "Item 2", 14 "Item 3", 15 "Item 4", 16 "Item 5", 17 "Item 6", 18 "Item 7", 19 "Item 8", 20 "Item 9", 21 "Item 10" 22 ); 23 } 24 }
【1】模塊的主要的功能有兩個
①對Acitivity中的Listview的Item的點擊事件的處理響應;
②Acitivity在獲取焦點時觸發presenter,讓Model構造數據,而後從Model中取出生成的List<String> 數據設置給Activity中的ListView的Adapter。
【2】調用的順序
【2-1】對Acitivity中的Listview的Item的點擊事件的處理響應:注意:與Model沒有發生聯繫
使用到了兩個接口:
【接口1】(MainPresenter接口)onItemClicked(int position):將點擊的position位置參數傳遞給代理實現類MainPresenterImpl;實現對int position參數的傳遞;
【接口2】(MainView接口) :showMessage(String message):將代理類中格式化好的position數據進行回傳給MainView接口的實現類MainActivity;實現對String Message參數的傳遞;
說白了,就是對position參數和String Message參數的回傳;
【2-2】Acitivity在獲取焦點時觸發presenter,讓Model構造數據,而後從Model中取出生成的List<String> 數據設置給Activity中的ListView的Adapter。
使用到了三個接口:上圖中的【1-3】是屬於view向Model發送請求,讓Model構造數據;【3-5】由Model構造好的數據向View進行回傳,而後最終設置給ListViewAdapter;
是一個有去有回的過程,去的過程是發送信號,回的過程是回傳數據。
【接口1】(MainView--setItems(List<String> items)):回調Presenter已經構造好的數據,實現對List<String> items參數的回傳;
【接口2】(MainPresenter --void onResume())觸發Model中的接口findItemsInteractor.findItems(this)進行數據的構造。
(MainPresenter --void onFinished(List<String> items) :完成對數據的回傳,設置給MainView :mainView.setItems(items); //將nodel返回的數據在View中進行了設置
【接口3】(FindItemsInteractor-->findItems(OnFinishedListener listener):觸發Model構造數據
【1】構造三個接口,分別對應着View-Presenter-Model。兩兩一組。
View接口:主要暴露給Presenter使用。
1 public interface LoginView { 2 void showProgress(); 3 4 void hideProgress(); 5 6 void setUsernameError(); 7 8 void setPasswordError(); 9 10 void navigateToHome(); //view的頁面的跳轉 11 }
1 public interface MainView { 2 3 void showProgress(); 4 5 void hideProgress(); 6 7 void setItems(List<String> items); 8 9 void showMessage(String message); 10 }
Presenter接口:
1 public interface LoginPresenter { 2 3 void validateCredentials(String username, String password); 4 5 void onDestroy(); 6 }
1 public interface MainPresenter { 2 3 void onResume(); 4 5 void onItemClicked(int position); 6 7 void onDestroy(); 8 }
Model接口:
兩部分構成,一部分是給Presenter實現的Listener,主要是Model對View的數據回傳、狀態的回調,主要是被Model調用。
另一部分是View傳遞的數據處理/請求,被View調用的方法。
1 public interface LoginInteractor { 2 3 interface OnLoginFinishedListener { //被presenter實現的接口 4 void onUsernameError(); 5 void onPasswordError(); 6 void onSuccess(); 7 } 8 9 //對view傳遞的數據的處理,此處參數有presenter實現的接口對象 OnLoginFinishedListener 10 void login(String username, String password, OnLoginFinishedListener listener); 11 12 }
1 public interface FindItemsInteractor { 2 3 interface OnFinishedListener { //presenter實現了此接口 4 void onFinished(List<String> items); 5 } 6 7 void findItems(OnFinishedListener listener); 8 }
【2】Acitivity只負責UI更新和數據設置。
在Acitivity中持有Presenter的接口對象。
Activity中控件具備的顯示/更新/數據的設置(ListView的Adapter)/數據的處理(登陸名和密碼的傳遞)以接口的形式暴露給Prsenter。只容許Presenter操做。
Acitivity的控件的更新時機交給Presenter直接決定,由Model間接決定。
【3】在Presenter中同時持有view和Model的接口對象。
【4】Presenter中除了實現自己的接口presenter接口,還須要實現Model對應的接口中的內部接口。
內部接口主要完成對狀態的回傳或者是數據的回傳。
源碼地址: