MVP及Retrofit简单学习

2017-06-08  本文已影响0人  落叶随风花落入泥

MVP 字母的含义

M:modle 提供数据 如:bean dao db net(网络请求接口)</br>
P:  presenter 负责逻辑的处理 如:网络框架,网络请求数据
V:View 界面展示  如:Activity ,Adapter ,Fragment

Retrofit 使用步骤(依赖接口的形式)

使用Retrofit服务器最好返回的是一个code 和一个json串的形式,这样我们就能提前写Javabean,也能在Presenter模块进行抽取。

1.1 添加依赖
 compile 'com.squareup.retrofit2:converter-gson:2.2.0'
 1.2 创建Retrofit对象进行解析,代码如下
  Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constant.BASEURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

MVP+Retrofit实战总结

外卖项目的梳理

登录模块

1 首先要创建一个basePresenter 在这个类中我们创建了Retrofit 对象和
CallBack 回调接口,代码如下:

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

public BasePresenter() {
    errorMap = new HashMap<>();
    errorMap.put("1","此页数据没有更新");
    errorMap.put("2","服务器忙");
    errorMap.put("3","请求参数异常");
    //创建Retrofit对象
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constant.BASEURL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    //指定Retrofit如何发送具体的请求
    //请求方式  get post
    //请求路径  url
    //请求参数
    //请求结果
    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中的数据可用
            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的短信
我们创建登录 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;//保持时间递减的状态码
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();
                //必须获取校验成功,才可以继续下一个发送请求做登录过程
                login();
                break;
            case SUBMIT_CODE_FAIL:
                Toast.makeText(LoginActivity.this,"校验验证码失败",Toast.LENGTH_SHORT).show();
                break;
            case KEEP_TIME_MINS:
                tvUserCode.setText("稍后再发("+(time--)+")");
                break;
            case RESET_TIME:
                tvUserCode.setText("重新发送");
                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){
                //下发验证码短信成功后,才可以做验证码短信+手机号码校验过程
                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){
                //下发验证码短信成功后,才可以做验证码短信+手机号码校验过程
                handler.sendEmptyMessage(GET_CODE_FAIL);
            }
            if (event == SMSSDK.EVENT_SUBMIT_VERIFICATION_CODE){
                //校验验证码失败
                handler.sendEmptyMessage(SUBMIT_CODE_FAIL);
            }
        }
        //做某一个事件结果的监听
        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);

    //对下发验证码短信的事件结果进行监听
    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:
            //判断手机号是否为空,是否合法,如果满足以上条件,就需要发送验证码短信
            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)){
        //下发验证码短信(发送成功,失败 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,则说明还有计数的时间
                while(time>0){
                    try {
                        Thread.sleep(999);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //发送一条消息,用于减少time的时间
                    handler.sendEmptyMessage(KEEP_TIME_MINS);
                }
                //重新下发验证码短信
                handler.sendEmptyMessage(RESET_TIME);

            }
        }.start();
    }
  }
 }

3 Retrofit 在请求网络数据需要我们进行网络接口的编写

 public interface ResponseInfoApi {
//请求方式  get post
//请求路径  url
//请求参数  key = value
//请求结果
//http://10.0.2.2:8080/TakeoutServiceVersion2/home?latitude=value&longitude=value发送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 网络请求框架,我们需要创建一个拼接url的接口
2.  如果多个界面复杂逻辑,我们要创建basepresenter,在里面创建Retrofit对
象,CallBack 回调,和数据解析的接口,错误信息接口(可选),让子类重写
后两个接口,进行数据的解析和异常时进行错误信息说明
3.在我们UI界面,只是做了初始化控件,点击事件,获取Editext的内容,
 shareSDK短信验证码,和presenter链接是通过创建presenter对象的方式,通
 过 对象调用方法,把我们获取的参数传递过去,在presenter的父类
 basepresenter中我们已经通过retrofit.create()方法,创建了网络请求url接口对
象,通过这个对象,把我们UI界面传递过来的参数进行拼接生成的对象为A(A是
举例子),在通过其异步请求数据,A..enqueue(new CallBackAdapter()); 这样我
们就完成了短信验证+登录的双重操作
上一篇下一篇

猜你喜欢

热点阅读