MVP及Retrofit简单学习

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()); 这样我
们就完成了短信验证+登录的双重操作
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容