美文网首页
MVP及Retrofit简单学习

MVP及Retrofit简单学习

作者: 落叶随风花落入泥 | 来源:发表于2017-06-08 14:20 被阅读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()); 这样我
    们就完成了短信验证+登录的双重操作

    相关文章

      网友评论

          本文标题:MVP及Retrofit简单学习

          本文链接:https://www.haomeiwen.com/subject/lkttqxtx.html