Android中MVP設計模式實例

MVP(Model ViewPresenter)模式是著名的MVC(Model ViewController)模式的一個演化版本,目前它在Android應用開發中越來越重要了。初看起來我們會感覺增加了很多類接口代碼看起來更加清晰。

請參考百度百科的MVP設計模式的講解

MVP設計模式的核心思想:針對接口編程,而不是針對實現編程
個人認爲MVP模式比較適合中小型的項目。如果項目過大,可以採用模塊化接口編程。就是將接口 根據自己業務需求分爲 幾個大的接口模塊,然後再分別來實現小的模塊。

具體來看看實際應用

做一個登錄的小demo:
先來看一下目錄



根據代碼來講解這個流程 
1、定義兩個實體類,ResponseBO  這個實體類裏面包含 code,和msg兩個字段,用來存儲服務器放回的responsecode和message。  UserBO-用戶實體類         
2、定義兩個接口。 一個是實時跟蹤AsyncTask的每個過程的接口。 一個是Login的接口
/**
* @ClassName: ResponseApi 
* @Description: 異步任務的回調接口類,相當於 Asynctask中的三個方法
* @author libiao
* @date 2015 -11 -6 下午3:04:22 
*
 */
public interface ResponseApi {
      /**
       * @Title: onStart
       * @Description: 異步任務啓動的時候。相當於AsyncTask中的 onstart()方法
       * @return: void
       */
      public void onStart();
      
      /**
       * @Title: ondoinBack
       * @Description: 異步任務執行過程中。相當於AsyncTask中的doInBackground()方法
       * @return: void
       */
      public void ondoinBack();

      /**
       * @Title: onSuccess
       * @Description: 異步任務執行完畢的方法,相當於AsyncTask中的onPostExecute()方法,實現此接口。這個方法們無論服務器返回的狀態嗎是多少,都會進入此方法
       * @param response
       * @return: void
       */
      public void onSuccess(ResponseBO response);
}



/**
 * @ClassName: LoginApi
 * @Description:
 *               登錄的接口,如果項目比較大,可以採用模塊化命名,在這個接口下,可以有當前模塊的所有需要與服務器交互的方法(根據 api接口文檔來封裝
 *               ) ,比如我接口下面就一個登陸的方法,一個註冊的方法(註冊的方法的具體邏輯沒有實現)
 * @author libiao
 * @date 2015 -11 -6 下午3:12:14
 *
 */
public interface LoginApi {
      /**
       * @Title: login
       * @Description: 登陸的方法
       * @param activity activity對象
       * @param name 用戶名
       * @param password 密碼
       * @param api 回調接口
       * @return: void
       */
      public void login(Activity activity, String name, String password, ResponseApi api);

      public void regist(Activity activity, String phone, String auCode, String password, ResponseApi api);
}


3、爲兩個接口提供實現的方法,首先看一下ResponseApiImpl,爲什麼要定義這個抽象類來實現ResponseApi接口呢? 因爲如果實現ResponseApi接口,其中的每個方法就必須要實現, 有些方法是我們可能不需要的,比如:ondoinBack()方法。所以在接口實例化的時候,是實例化ResponseApiImpl這個類,而不是實例化ResponseApi。


import com.example.mvp.service.ResponseApi;

/**
* @ClassName: ResponseApiImpl  
* @Description: 實現了  ResponseApi接口,在調用ResponseApi接口的時候,實例化此類,可以不用必須實現onStart(),ondoinBack()方法
* @author libiao 
* @date 2015-11-6 下午3:21:04  
*
 */
public abstract class ResponseApiImpl implements ResponseApi {
	@Override
	public void onStart() {

	}

	@Override
	public void ondoinBack() {

	}
}




接着來看一看LoginApiImpl實現類,這裏是主要的業務邏輯!

/**
* @ClassName: LoginApiImpl 
* @Description: 實現 LoginApi,所有的login模塊的業務邏輯都在此處,所以Activity界面無需任何複雜邏輯,MVP模式的核心邏輯
* @author libiao
* @date 2015 -11 -6 下午3:22:15 
*
 */
public class LoginApiImpl implements LoginApi{
      
      @Override
      public void login(Activity activity, String name, String password, ResponseApi api) {
            //在這裏你可以對傳進來的數據進行校驗,如果校驗失敗則可以作出相應的處理,我這裏只是彈出提示
             if(name== null|| "".equals(name)){
                  Toast. makeText(activity, "用戶名不能爲空", Toast.LENGTH_SHORT).show();
                   return;
            }
             if(password== null|| "".equals(password)){
                  Toast. makeText(activity, "密碼不能爲空", Toast.LENGTH_SHORT).show();
                   return;
            }
            JSONObject json = new JSONObject();
             try {
                  json.put( "username", name);
                  json.put( "password", password);
            } catch (JSONException e) {
                  e.printStackTrace();
            }
             new MsgAsyncTask(activity, json.toString(), api, APPConstants.URL_LOGIN).execute();
      }

      @Override
      public void regist(Activity activity, String phone, String auCode, String password, ResponseApi api) {
            
      }
}<span style="color:#ff0000;">
</span>

最後來看一異步任務類吧,這裏主要是執行與服務器的交互

/**
 *
* @ClassName: MsgAsyncTask 
* @Description:  發送普通字符串給服務器的異步任務 
* @author libiao
* @date 2015 -11 -6 下午2:37:26 
*
 */
public class MsgAsyncTask extends WeakAsyncTask<Void, Void, ResponseBO, Context>{
      private String json;
      private ResponseApi api;
      private String url;
      /**
       * @Title:MsgAsyncTask
       * @Description:構造方法
       * @param activity Activiyt對象
       * @param json 要發送給服務器端的字符串
       * @param api 回調接口
       * @param url 服務器地址
       */
      public MsgAsyncTask(Activity activity,String json,ResponseApi api,String url) {
             super(activity);
             this. json=json;
             this. api=api;
             this. url=url;
      }
      @Override
      protected void onPreExecute(Context target) {
             // TODO Auto-generated method stub
             super.onPreExecute(target);
             api.onStart();
      }
      @Override
      protected ResponseBO doInBackground(Context target, Void... params) {
             api.ondoinBack();
             return HttpUtil. getInstance().post(json, url);
      }
      @Override
      protected void onPostExecute(Context target, ResponseBO result) {
             super.onPostExecute(target, result);
             api.onSuccess(result);
      }
      
}

HttpUtil類:
public class HttpUtil {
      private final static String REQUEST_MOTHOD = "POST";
      private final static int TIME_OUT = 15000;

      private static HttpUtil instance = null;

      private HttpUtil() {
      }

      public static HttpUtil getInstance() {
             if ( instance == null) {
                   instance = new HttpUtil();
            }
             return instance;
      }

      public ResponseBO post(String json, String url) {
            ResponseBO bo = new ResponseBO();
            HttpURLConnection connection = getConnection(url);
             try {
                  connection.setRequestProperty( "Content-Length", String.valueOf(json.getBytes().length));
                  OutputStream os = connection.getOutputStream();
                  os.write(json.getBytes( "UTF-8"));
                  os.flush();
                   int code = connection.getResponseCode();
                  bo.setResPonseCode(code);
                   if (connection.getResponseCode() == 200) {
                         // 獲取響應的輸入流對象
                        InputStream is = connection.getInputStream();
                         // 創建字節輸出流對象
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                         // 定義讀取的長度
                         int len = 0;
                         // 定義緩衝區
                         byte buffer[] = new byte[1024];
                         // 按照緩衝區的大小,循環讀取
                         while ((len = is.read(buffer)) != -1) {
                               // 根據讀取的長度寫入到 os對象中
                              baos.write(buffer, 0, len);
                        }
                         // 釋放資源
                        is.close();
                        baos.close();
                        bo.setResPonseMsg( new String(baos.toByteArray()));
                  }
            } catch (IOException e) {
                   // TODO Auto-generated catch block
                  e.printStackTrace();
            }
            connection.disconnect();
             return bo;
      }

      private HttpURLConnection getConnection(String path) {
            HttpURLConnection connection = null;
             // 初始化connection
             try {
                   // 根據地址創建URL對象
                  URL url = new URL(path);
                   // 根據URL對象打開鏈接
                  connection = (HttpURLConnection) url.openConnection();
                   // 設置請求的方式
                  connection.setRequestMethod( REQUEST_MOTHOD);
                   // 發送POST請求必須設置允許輸入,默認爲true
                  connection.setDoInput( true);
                   // 發送POST請求必須設置允許輸出
                  connection.setDoOutput( true);
                   // 設置不使用緩存
                  connection.setUseCaches( false);
                   // 設置請求的超時時間
                  connection.setReadTimeout( TIME_OUT);
                  connection.setConnectTimeout( TIME_OUT);
                  connection.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" );
            } catch (IOException e) {
                  e.printStackTrace();
            }
             return connection;
      }

}

最後來看一下如何調用:

            String name = edtName.getText().toString(); //得到用戶名
            String password = edtPassword.getText().toString(); //得到密碼
             // 實例化接口,MVP的核心思想就是針對接口編程而不是針對實現編程
             LoginApi api = new LoginApiImpl();
             // 調用接口請求服務器數據,服務器返回的數據回調在ResponseApiImpl的onSuccess()方法裏面,可以根據自己的需求來實現onStart()和ondoinBack()方法
            api.login(MainActivity. this, name, password, new ResponseApiImpl() {

                   @Override
                   public void onSuccess(ResponseBO response) {
                        Toast. makeText(MainActivity.this, response.getResPonseCode() + ">>>>" + response.getResPonseMsg(), Toast.LENGTH_LONG) .show();
                  }
            });


Eclipse項目地址:http://download.csdn.net/detail/q908555281/9247833

Android Studio項目地址:https://github.com/townkoim/Mvp





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章