Android当中的MVP模式(五)封装之后的OkHttp工具在Model层的使用

摘要:在上一篇中对 OkHttp 进行了简单的封装,但是没有使用到这个系列当中的 Demo 里面,这一章就使用上一篇封装的 OkHttp 工具,替换掉之前 Demo 里面的 Model 层的网络请求.并且之前的部分接口方法都没有使用,比如说 IBasePresenter 接口中的 HashMap getParams() 方法, IBasePaginationPresenter 中的 boolean hasMoreData() 方法,算是对上一篇的补充。

Model 层原来的写法

拿分页数据获取的 Model 层举例,当时在 SohuAlbumModel 中是这样获取数据的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Override
public void sendRequestToServer(Param param) {
String validUrl = null;
Log.d(TAG, ">> sendRequestToServer >> " + "has more data ?" + mPaginationPresenter.hasMoreData());
if (param != null && !TextUtils.isEmpty(url) && mPaginationPresenter.hasMoreData()) {
validUrl = getValidUrl(url, param);
Log.d(TAG, ">> sendRequestToServer >> " + "ValidUrl:" + validUrl);
}
if (!TextUtils.isEmpty(validUrl)) {
HttpUtils.executeByGet(validUrl, new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, ">> onFailure >> ");
e.printStackTrace();
mPaginationPresenter.okHttpError(Constants.URL_ERROR, e.getMessage(), url);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
Log.d(TAG, ">> onResponse >> " + "Not successful");
mPaginationPresenter.okHttpError(Constants.SERVER_ERROR, response.message(), url);
}
String responseJson = response.body().string();
Log.d(TAG, ">> onResponse >> " + "responseJson:" + responseJson);
mPaginationPresenter.accessSuccess(responseJson);
}
});
} else {
Log.d(TAG, ">> sendRequestToServer >> " + "Valid Url is empty");
}
}
private String getValidUrl(String url, Param param) {
return String.format(url, param.getPageIndex(), param.getPageSize());
}

url 当中的参数是直接在 sendRequestToServer 方法中传递进来的,这么一来会让 Model 层的职责变得不那么单一,因为 Model 层只应该负责数据相关的工作,此处的 params 传递进来,还需要进行一个 url 的拼接工作,所以在这里是可以优化的地方。

在看看上一篇中的 OkHttpManager 类中请求服务器数据的核心方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 使用{@link OkHttpClient}想服务器端请求数据的方法
* @param method {@link Constants#HTTP_GET_METHOD} Get方式,{@link Constants#HTTP_POST_METHOD} Post方式
* @param baseUrl baseUrl
* @param paramsMap 请求url的参数,以键值对的形式存放
* @param handler
*/
public void requestServerData(int method, String baseUrl, HashMap<String, String> paramsMap, DisposeDataHandler handler) {
RequestParams requestParams = new RequestParams(paramsMap);
Request request = null;
if (method == Constants.HTTP_GET_METHOD) {
request = CommonRequest.createGetRequest(baseUrl, requestParams);
} else if (method == Constants.HTTP_POST_METHOD) {
request = CommonRequest.createPostRequest(baseUrl, requestParams);
}
if (request != null) {
mOkHttpClient.newCall(request).enqueue(new CommonJsonCallback(handler));
}
}

使用 OkHttpManager 来请求服务器获得数据,第二个参数 HashMap<String, String> paramsMap 就是已经在 Presenter 层中处理好的键值对参数,然后在 CommonRequest.createGetRequest(baseUrl, requestParams); 或者是 CommonRequest.createPostRequest(baseUrl, requestParams) 中就已经把完整的 url 拼接出来了。具体如何拼接,如何构造 Request 对象,Model 层完全不用关心,它只需要在请求成功或者是请求失败的回调接口中将数据回调到 Presenter 层去即可。

那么现在就开始重构 Model 层的方法。

Model 层现在的写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public void sendRequestToServer() {
if (mPaginationPresenter.hasMoreData()) {
OkHttpManager.getInstance().requestServerData(method, baseUrl, mPaginationPresenter.getParams(), new DisposeDataHandler(new DisposeDataListener() {
@Override
public void onSuccess(Object responseObj) {
String responseJson = (String) responseObj;
Log.d(TAG, ">> onSuccess >> " + responseJson);
mPaginationPresenter.accessSuccess(responseJson);
}
@Override
public void onFailure(OkHttpException exception) {
Log.d(TAG, ">> onFailure >> " + exception.getErrorCode());
mPaginationPresenter.okHttpError(exception.getErrorCode(), exception.getErrorMsg(), url);
}
}, null));
}else {
Log.d(TAG,">> sendRequestToServer >> " + "No more data!");
}
}

是不是简单了很多!和之前的方法相比较,有三处不同的地方:

  • 2 行的 sendRequestToServer() 方法中已经没有了 param 参数了。(那么参数从哪儿来呢?)
  • 3 行多了一个 hasMoreData() 的方法,用于判断服务器端还有没有更多的数据。若没有,那就没有必要去请求了。它是在哪儿初始化的?
  • 4 行的多了 mPaginationPresenter.getParams() ,它是在什么地方初始化的?
  • 4 行的 baseurl 不是之前 Model 层的 url

下面就解释为什么可以这么操作。

BasePaginationPresenter 的修改

观察之前 Model 层的写法就知道,这个地方的参数,主要是从其中取出 pageIndexpageSize ,用于拼接新的 url ,然后再请求数据,这儿不需要这个参数了, 那肯定就是有地方已经提供了这个参数了咯。 对,就是 mPaginationPresenter.getParams() 这个之前没有用过的方法,先回顾一下这个方法在哪儿定义的:

1
2
3
4
5
6
7
8
9
10
11
public interface IBasePresenter<Param> {
//省略部分代码
/**
* 在Model层中调用,此方法用于获取Presenter层处理好的参数
* @author zfy
* @return 请求参数
* @Created at 2017/10/21/021 15:05
*/
HashMap<String, String> getParams();
}

第二篇中,针对每一层封装的时候,这个接口就已经定义好了,只是一直没有使用上,在这儿就用上了。而 BasePaginationPresenter 类是实现这个街口的,并且这个 Presenter 是分页请求数据中 Presenter 层的基类,在第三篇也提到过。下面看看 BasePaginationPresenter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* @author:ZengFanyu
* @date:2017/10/20
*/
public abstract class BasePaginationPresenter<Param extends BasePaginationParam, Data> implements IBasePaginationPresenter<Param> {
//省略部分代码
/**
* 子类实现,用于确认服务器端是否还有数据
*
* @return true-还有数据 false-没有数据
*/
public abstract boolean serverHaveMoreData();
/**
* 子类实现,用于返回请求服务器的url当中的参数
*
* @return HashMap<String,String> url 中的 kay value 对
*/
public abstract HashMap<String, String> getHttpRequestParams();
//省略部分代码
@Override
public HashMap<String, String> getParams() {
return getHttpRequestParams();
}
@Override
public boolean hasMoreData() {
return serverHaveMoreData();
}
}

只贴出和之前不同的部分,

  • 多了一个 serverHaveMoreData() 抽象方法,子类去实现的,用于判断服务器还有没有更多的数据。
  • 多了以个 getHttpRequestParams() 抽象方法,子类去实现,用于将参数填充到 HashMap 中,供 Model 层使用。

接下里看看子类 AlbumPresenter 的实现:

AlbumPresenter 的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* @author:ZengFanyu
* Function:
*/
public class AlbumPresenter extends BasePaginationPresenter<BasePaginationParam, Album> {
private int mTotalCount=-1;
public AlbumPresenter(BaseMvpActivity baseListView, Class<Album> aClass) {
super(baseListView, aClass);
this.mBaseListView = baseListView;
getModel().setRequestMethod(Constants.HTTP_GET_METHOD);
getModel().setRequestUrl(Constants.SOHU_SERIALS_URL_BASE);
}
//省略代码
@Override
public void serverResponse(Album album) {
//省略代码
mTotalCount = album.getData().getCount();
}
@Override
public boolean serverHaveMoreData() {
//此处pageIndex是从1开始的, 实际适用需要注意pageIndex的起始值
int pageSize = mParam.getPageSize();
int pageIndex = mParam.getPageIndex();
//第一次需要返回true 才能进到 serverResponse 方法中去初始化 mTotalCount 值
return mTotalCount == -1 || (pageIndex * pageSize) <= mTotalCount;
}
@Override
public HashMap<String, String> getHttpRequestParams() {
HashMap<String, String> paramsMap = new HashMap<>();
paramsMap.put("cid", "2");
paramsMap.put("o", "1");
paramsMap.put("plat", "6");
paramsMap.put("poid", "1");
paramsMap.put("api_key", "9854b2afa779e1a6bff1962447a09dbd");
paramsMap.put("sver", "6.2.0");
paramsMap.put("sysver", "4.4.2");
paramsMap.put("partner", "47");
paramsMap.put("page", String.valueOf(mParam.getPageIndex()));
paramsMap.put("page_size", String.valueOf(mParam.getPageSize()));
return paramsMap;
}
}

与之前实现不同地方在于:

  • 构造方法当中设置的 url ,现在是 baseUrl ,后面的参数由 getHttpRequestParams方法生成,在CommonRequest 中生成完整 url
  • serverResponse() 方法中,对 mTotalCount 进行了初始化, 这个值就是记录服务器端一共有多少条数据的。
  • serverHaveMoreData()拿当前已经加载的数据条数和 mTotalCount 进行对比,判断是否还有数据。
  • getHttpRequestParams() 构造参数的 HashMap

小结

从这一章的从重构部分代码,很明显可以看到,各层之间的依赖关系:

  • 主要是替换网络请求的工具,那么就是只涉及到 Model 层的改动。
  • 这里 Presenter 层改动了,其实是不需要改动的, 这里改动了的原因是,我把之前没有实现的功能补上了,并且将sendRequestToServer() 的参数去掉了导致的。
  • 可以发现, View 层代码没有进行一点修改,也就是 Activity 并没有动。
共82.3k字
0%
.gt-container a{border-bottom: none;}