版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
前言 :
Android Mvp 模式是现在常用的设计模式,将视图和业务逻辑解耦,分为Model-View-Presenter三个部分。
1.M 层 为数据模型 做一些数据相关的处理
2.P 层 控制View 层 为UI 交互的发起者 接受M层的反馈 然后对 View层的控制
3.V 层 接受P层的控制改变UI
今天我们要讲的是一个MVP的一个库 Mosby 他能更好的实现MVP,让实现MVP更加的快捷,方便更加清晰的搭建MVP。
开源地址:https://github.com/sockeqwe/mosby
官方介绍:http://hannesdorfmann.com/mosby/mvp/
依赖
implementation 'com.hannesdorfmann.mosby:mvp:2.0.1'
implementation 'com.hannesdorfmann.mosby:viewstate:2.0.1'
程序实现
使用Mosby 编写一个应用程序,界面一个Button 一个EditView 一个TextView
- 输入框输入电话号码
- 点击按钮,请求接口查血电话号码的归属地
- 显示电话号码的归属地
使用到的技术
- Mosby
- RxJava
- OkHttp
1. Model 数据模型层
定义从服务器返回的数据 Bean
Bean数据
/**
* resultcode : 200
* reason : Return Successd!
* result : {"province":"四川","city":"成都","areacode":"028","zip":"610000","company":"移动","card":""}
* error_code : 0
*/
生成实体类,通过工具生成。
package com.hzy.phone.model;
public class PhoneInfo {
/**
* resultcode : 200
* reason : Return Successd!
* result : {"province":"四川","city":"成都","areacode":"028","zip":"610000","company":"移动","card":""}
* error_code : 0
*/
private int resultcode;
private String reason;
private ResultBean result;
private int error_code;
public int getResultcode() {
return resultcode;
}
public void setResultcode(int resultcode) {
this.resultcode = resultcode;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public ResultBean getResult() {
return result;
}
public void setResult(ResultBean result) {
this.result = result;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
public static class ResultBean {
/**
* province : 四川
* city : 成都
* areacode : 028
* zip : 610000
* company : 移动
* card :
*/
private String province;
private String city;
private String areacode;
private String zip;
private String company;
private String card;
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAreacode() {
return areacode;
}
public void setAreacode(String areacode) {
this.areacode = areacode;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public String getCard() {
return card;
}
public void setCard(String card) {
this.card = card;
}
}
}
定义model层数据返回接口 成功 和 失败
public interface QueryModeListener {
void onQuerySuccess(PhoneInfo phoneInfo);
void onQueryError(int code);
}
编写Model层的数据请求实现,传入model的接口监听,回调成功和失败。通过RxJava 进行网络请求的线程切换。
public static void queryPhoneNumber(String phonenumber, final QueryModeListener queryModeListener) {
final Map<String, Object> headerMap = new HashMap<>();
headerMap.put("phone", phonenumber);
final Map<String, Object> queryMap = new HashMap<>();
queryMap.put("key", "e8884c80009b02439019b4ee99c0d2a5");
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
e.onNext(doGet(mUrl, headerMap, queryMap));
e.onComplete();
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
Gson gson = new Gson();
PhoneInfo phoneInfo = gson.fromJson(s, PhoneInfo.class);
if (phoneInfo.getResultcode() == QUERY_SUCCESS) {
queryModeListener.onQuerySuccess(phoneInfo);
} else {
queryModeListener.onQueryError(phoneInfo.getError_code());
}
Log.e(TAG, "onNext: ");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
Log.e(TAG, "onComplete: ");
}
});
}
请求数据的Okhttp,网络请求功能的实现
private static String mUrl = "http://apis.juhe.cn/mobile/get?";
private static String TAG = "QueryModel";
private final static int QUERY_SUCCESS = 200;
/**
* get 请求
*
* @param url url
* @param header 请求头参数
* @param query 参数
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.N)
private static String doGet(String url, Map<String, Object> header, Map<String, Object> query) throws Exception {
OkHttpClient client = new OkHttpClient();
// 创建一个请求 Builder
Request.Builder builder = new Request.Builder();
// 创建一个 request
Request request = builder.url(url).build();
final HttpUrl.Builder urlBuilders = request.url().newBuilder();
Iterator<Map.Entry<String, Object>> headerIterator = header.entrySet().iterator();
headerIterator.forEachRemaining(new Consumer<Map.Entry<String, Object>>() {
@Override
public void accept(Map.Entry<String, Object> e) {
urlBuilders.addQueryParameter(e.getKey(), String.valueOf(e.getValue()));
}
});
// 装载请求的参数
Iterator<Map.Entry<String, Object>> queryIterator = query.entrySet().iterator();
queryIterator.forEachRemaining(new Consumer<Map.Entry<String, Object>>() {
@Override
public void accept(Map.Entry<String, Object> e) {
urlBuilders.addQueryParameter(e.getKey(), (String) e.getValue());
}
});
// 设置自定义的 builder
builder.url(urlBuilders.build());
try (Response execute = client.newCall(builder.build()).execute()) {
return execute.body().string();
}
}
2.presenter 层的实现
P层主要思想为沟通M层和V层的数据交互和显示
QueryPhonePresenter 继承 MvpBasePresenter<QueryPhoneView> 注:QueryPhoneView是我们定义的View层的接口
public class QueryPhonePresenter extends MvpBasePresenter<QueryPhoneView> {
@RequiresApi(api = Build.VERSION_CODES.N)
public void queryPresenter(String phoneNuber) {
QueryModeListener queryModeListener = new QueryModeListener() {
@Override
public void onQuerySuccess(PhoneInfo phoneInfo) {
QueryPhoneView queryPhoneView = getView();
if (queryPhoneView != null) {
queryPhoneView.onQuerySuccess(phoneInfo);
}
}
@Override
public void onQueryError(int code) {
QueryPhoneView queryPhoneView = getView();
if (queryPhoneView != null) {
queryPhoneView.onError(code);
}
}
};
QueryModel.queryPhoneNumber(phoneNuber, queryModeListener);
}
}
实现model的接口,通过getView方法获取到View层的接口,然后进行View层的接口回调,实现改变View,最后调用Model的数据请求功能。
注:getView方法需要判null
3.View层的实现
定义View层的接口
public interface QueryPhoneView extends MvpView {
void onQuerySuccess(PhoneInfo phoneInfo);
void onError(int code);
}
最后Activity 继承 MvpActivity<QueryPhoneView, QueryPhonePresenter> 实现接口QueryPhoneView
public class MainActivity extends MvpActivity<QueryPhoneView, QueryPhonePresenter> implements QueryPhoneView, View.OnClickListener {
private Button mQueryBt;
private EditText mQueryEt;
private TextView mQueryTv;
private QueryPhonePresenter mQueryPhonePresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mQueryBt = findViewById(R.id.query_bt);
mQueryEt = findViewById(R.id.nuber_et);
mQueryTv = findViewById(R.id.dispaly_tv);
mQueryBt.setOnClickListener(this);
}
@NonNull
@Override
public QueryPhonePresenter createPresenter() {
if (mQueryPhonePresenter == null) {
mQueryPhonePresenter = new QueryPhonePresenter();
}
return mQueryPhonePresenter;
}
@Override
public void onQuerySuccess(PhoneInfo phoneInfo) {
PhoneInfo.ResultBean resultBean = phoneInfo.getResult();
mQueryTv.setText(resultBean.getCity());
}
@Override
public void onError(int code) {
mQueryTv.setText("ErrorCode" + code);
}
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public void onClick(View v) {
mQueryPhonePresenter.queryPresenter(mQueryEt.getText().toString());
}
}
重写方法createPresenter 从中获取到P层的实列。总体来说mosby减少了一些不必要的代码,让代码逻辑看起来更加的清晰,易懂。
效果展示