MVP及Retrofit簡單學習

MVP 字母的含義

M:modle 提供數(shù)據(jù) 如:bean dao db net(網(wǎng)絡請求接口)</br>
P:  presenter 負責邏輯的處理 如:網(wǎng)絡框架,網(wǎng)絡請求數(shù)據(jù)
V:View 界面展示  如:Activity ,Adapter ,Fragment

Retrofit 使用步驟(依賴接口的形式)

使用Retrofit服務器最好返回的是一個code 和一個json串的形式,這樣我們就能提前寫Javabean,也能在Presenter模塊進行抽取。

1.1 添加依賴
 compile 'com.squareup.retrofit2:converter-gson:2.2.0'
 1.2 創(chuàng)建Retrofit對象進行解析,代碼如下
  Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constant.BASEURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

MVP+Retrofit實戰(zhàn)總結

外賣項目的梳理

登錄模塊

1 首先要創(chuàng)建一個basePresenter 在這個類中我們創(chuàng)建了Retrofit 對象和
CallBack 回調接口,代碼如下:

public abstract class BasePresenter {
protected ResponseInfoApi responseInfoApi;
private HashMap<String, String> errorMap;

public BasePresenter() {
    errorMap = new HashMap<>();
    errorMap.put("1","此頁數(shù)據(jù)沒有更新");
    errorMap.put("2","服務器忙");
    errorMap.put("3","請求參數(shù)異常");
    //創(chuàng)建Retrofit對象
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constant.BASEURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    //指定Retrofit如何發(fā)送具體的請求
    //請求方式  get post
    //請求路徑  url
    //請求參數(shù)
    //請求結果
    responseInfoApi = retrofit.create(ResponseInfoApi.class);
}

//如何處理結果(2個方法回調方法)
//同步?httpUrlConnection
//異步?回調方法(成功,失敗)
class CallBackAdapter implements Callback<ResponseInfo>{
    @Override
    public void onResponse(Call<ResponseInfo> call, Response<ResponseInfo> response) {
        //獲取服務器返回的結果
        ResponseInfo body = response.body();
        if (body.getCode().equals("0")){
            //請求成功,data中的數(shù)據(jù)可用
            String json = body.getData();
            //json解析
            parseJson(json);
        }else{
            //本次請求有異常,具體的異常類型獲取出來
            String errorMessage = errorMap.get(body.getCode());
            //自定義一個運行時異常,讓onFailure方法接收
            onFailure(call,new RuntimeException(errorMessage));
        }
    }
    @Override
    public void onFailure(Call<ResponseInfo> call, Throwable t) {
        if (t instanceof RuntimeException){
            //onFailure方法自己調用
            String message = t.getMessage();
            //自定義一個如何顯示異常方法
            showErrorMessage(message);
        }
        //retrofit框架調用
        showErrorMessage("服務器忙,請稍后重試");
    }
}
//因為json串對于每一個頁面的請求而言,結果都是有差異的,所以無法做具體的解析,抽象
    protected abstract void parseJson(String json);
    protected abstract void showErrorMessage(String message);
}

2 M模塊我們 只進行了控件的初始化,按鈕的點擊事件,shareSDK的短信
我們創(chuàng)建登錄 Presenter 對象,通過這個類對象中的方法,把我們的
username password phone 等傳遞到Presenter中,邏輯在Presenter 中進
行處理。代碼如下:
public class LoginActivity extends BaseActivity {
private static final int GET_CODE_SUCCES = 100;//獲取驗證碼成功
private static final int GET_CODE_FAIL = 101;//獲取驗證碼失敗

private static final int KEEP_TIME_MINS = 102;//保持時間遞減的狀態(tài)碼
private static final int RESET_TIME = 103;//重置時間為60秒

private static final int SUBMIT_CODE_SUCCES = 104;//校驗驗證碼成功
private static final int SUBMIT_CODE_FAIL = 105;//校驗驗證碼失敗

@InjectView(R.id.iv_user_back)
ImageView ivUserBack;
@InjectView(R.id.iv_user_password_login)
TextView ivUserPasswordLogin;
@InjectView(R.id.et_user_phone)
EditText etUserPhone;
@InjectView(R.id.tv_user_code)
TextView tvUserCode;
@InjectView(R.id.et_user_psd)
EditText etUserPsd;
@InjectView(R.id.et_user_code)
EditText etUserCode;
@InjectView(R.id.login)
TextView login;
private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what){
            case GET_CODE_SUCCES:
                Toast.makeText(LoginActivity.this,"獲取驗證碼成功",Toast.LENGTH_SHORT).show();
                break;
            case GET_CODE_FAIL:
                Toast.makeText(LoginActivity.this,"獲取驗證碼失敗",Toast.LENGTH_SHORT).show();
                break;
            case SUBMIT_CODE_SUCCES:
                Toast.makeText(LoginActivity.this,"校驗驗證碼成功",Toast.LENGTH_SHORT).show();
                //必須獲取校驗成功,才可以繼續(xù)下一個發(fā)送請求做登錄過程
                login();
                break;
            case SUBMIT_CODE_FAIL:
                Toast.makeText(LoginActivity.this,"校驗驗證碼失敗",Toast.LENGTH_SHORT).show();
                break;
            case KEEP_TIME_MINS:
                tvUserCode.setText("稍后再發(fā)("+(time--)+")");
                break;
            case RESET_TIME:
                tvUserCode.setText("重新發(fā)送");
                time = 60;
                break;
        }
    }
};

private void login() {
    //電話
    String phone = etUserPhone.getText().toString().trim();
    //密碼
    String psd = etUserPsd.getText().toString().trim();
    //驗證碼
    String code = etUserCode.getText().toString().trim();
    if(SMSUtil.isMobileNO(phone) && !TextUtils.isEmpty(psd) && !TextUtils.isEmpty(code)){
        LoginPresenter loginPresenter = new LoginPresenter(this);
        loginPresenter.getLoginData(phone,psd,phone,2);
    }
}

//    EVENT_SUBMIT_VERIFICATION_CODE
private EventHandler eventHandler = new EventHandler(){
    @Override
    public void afterEvent(int event, int result, Object o) {
        //此方法是運行在子線程中的,所以不可以
        if (result == SMSSDK.RESULT_COMPLETE){
            //成功
            if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE){
                //下發(fā)驗證碼短信成功后,才可以做驗證碼短信+手機號碼校驗過程
                handler.sendEmptyMessage(GET_CODE_SUCCES);
            }
            if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){
                //校驗驗證碼成功
                handler.sendEmptyMessage(SUBMIT_CODE_SUCCES);
            }
        }else{
            //失敗
            if (event == SMSSDK.EVENT_GET_VERIFICATION_CODE){
                //下發(fā)驗證碼短信成功后,才可以做驗證碼短信+手機號碼校驗過程
                handler.sendEmptyMessage(GET_CODE_FAIL);
            }
            if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){
                //校驗驗證碼失敗
                handler.sendEmptyMessage(SUBMIT_CODE_FAIL);
            }
        }
        //做某一個事件結果的監(jiān)聽
        super.afterEvent(event, result, o);
    }
};
private int time = 60;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    ButterKnife.inject(this);

    //對下發(fā)驗證碼短信的事件結果進行監(jiān)聽
    SMSSDK.registerEventHandler(eventHandler);
}
@OnClick({R.id.tv_user_code,R.id.login})
public void onClick(View view){
    switch (view.getId()){
        case R.id.tv_user_code:
            //判斷手機號是否為空,是否合法,如果滿足以上條件,就需要發(fā)送驗證碼短信
            sendCode();
            break;
        case R.id.login:
            checkLogin();
            break;
    }
}

private void checkLogin() {
    //電話
    String phone = etUserPhone.getText().toString().trim();
    //密碼
    String psd = etUserPsd.getText().toString().trim();
    //驗證碼
    String code = etUserCode.getText().toString().trim();

    if(SMSUtil.isMobileNO(phone) && !TextUtils.isEmpty(psd) && !TextUtils.isEmpty(code)){
 //手機號碼和驗證碼,放再sharesdk平臺校驗過程
// SMSSDK.submitVerificationCode("86",phone,code);
        login();
    }
}

private void sendCode() {
    String phone = etUserPhone.getText().toString().trim();
    if(SMSUtil.isMobileNO(phone)){
        //下發(fā)驗證碼短信(發(fā)送成功,失敗 EventHandler --->afterEvent())
     SMSSDK.getVerificationCode("86",phone, new 
     OnSendMessageHandler() {
            @Override
            public boolean onSendMessage(String country, String phone) {
                return false;
            }
        });
        //子線程進行倒計時
        new Thread(){
            @Override
            public void run() {
                //如果time的值大于0,則說明還有計數(shù)的時間
                while(time>0){
                    try {
                        Thread.sleep(999);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //發(fā)送一條消息,用于減少time的時間
                    handler.sendEmptyMessage(KEEP_TIME_MINS);
                }
                //重新下發(fā)驗證碼短信
                handler.sendEmptyMessage(RESET_TIME);

            }
        }.start();
    }
  }
 }

3 Retrofit 在請求網(wǎng)絡數(shù)據(jù)需要我們進行網(wǎng)絡接口的編寫

 public interface ResponseInfoApi {
//請求方式  get post
//請求路徑  url
//請求參數(shù)  key = value
//請求結果
//http://10.0.2.2:8080/TakeoutServiceVersion2/home?latitude=value&longitude=value發(fā)送get請求
@GET(Constant.LOGIN)
Call<ResponseInfo> getLoginInfo(@Query("username") String username,@Query("password")String password,
                                @Query("phone")String phone, @Query("type")int type);

}

總結:

1. 我們用Retrofit 網(wǎng)絡請求框架,我們需要創(chuàng)建一個拼接url的接口
2.  如果多個界面復雜邏輯,我們要創(chuàng)建basepresenter,在里面創(chuàng)建Retrofit對
象,CallBack 回調,和數(shù)據(jù)解析的接口,錯誤信息接口(可選),讓子類重寫
后兩個接口,進行數(shù)據(jù)的解析和異常時進行錯誤信息說明
3.在我們UI界面,只是做了初始化控件,點擊事件,獲取Editext的內容,
 shareSDK短信驗證碼,和presenter鏈接是通過創(chuàng)建presenter對象的方式,通
 過 對象調用方法,把我們獲取的參數(shù)傳遞過去,在presenter的父類
 basepresenter中我們已經通過retrofit.create()方法,創(chuàng)建了網(wǎng)絡請求url接口對
象,通過這個對象,把我們UI界面?zhèn)鬟f過來的參數(shù)進行拼接生成的對象為A(A是
舉例子),在通過其異步請求數(shù)據(jù),A..enqueue(new CallBackAdapter()); 這樣我
們就完成了短信驗證+登錄的雙重操作
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容