此博文根据前面两篇文章 Android MVP 架构初试 Android MVP 架构封装 再结合主流框架Retrofit2+Rxjava来个实践

源码地址RxMVP

项目截图

Retrofit2+Rxjava 封装

JuHeService 数据请求接口

/**
* 请求示例:
* http://v.juhe.cn/dream/query
* q:梦境关键字,如:黄金 需要utf8 urlencode
* cid:指定分类,默认全部
* full: 是否显示详细信息,1:是 0:否,默认0
*/
public interface JuHeService {
@GET("dream/query")
Observable<HttpJuHeResult<List<JuHeDream>>> getDreams(@QueryMap Map<String, Object> options);
}

HttpJuHeMethods 聚合解梦封装的方法

public class HttpJuHeMethods {

    public static final String BASE_URL = "http://v.juhe.cn/";

    private static final int DEFAULT_TIMEOUT = 5;

    private Retrofit retrofit;

    private JuHeService juheService;

    //构造方法私有
private HttpJuHeMethods() {
//手动创建一个OkHttpClient并设置超时时间
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
httpClientBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build(); retrofit = new Retrofit.Builder()
.client(httpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(BASE_URL)
.build(); juheService = retrofit.create(JuHeService.class);
} //在访问HttpMethods时创建单例
private static class SingletonHolder{
private static final HttpJuHeMethods INSTANCE = new HttpJuHeMethods();
} //获取单例
public static HttpJuHeMethods getInstance(){
return SingletonHolder.INSTANCE;
} /**
* 用来统一处理Http的resultCode,并将HttpResult的Data部分剥离出来返回给subscriber
*
* @param <T> Subscriber真正需要的数据类型,也就是Data部分的数据类型
*/
private class HttpResultFunc<T> implements Func1<HttpJuHeResult<T>, T> { @Override
public T call(HttpJuHeResult<T> httpResult) {
if (httpResult.getError_code() != 0) {
throw new ApiException(httpResult.getError_code());
}
return httpResult.getResult();
}
} private <T> void toSubscribe(Observable<T> observable, Subscriber<T> subscriber){
observable.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
} /**
* 用于获取聚合笑话的数据
* @param subscriber 由调用者传过来的观察者对象
* @param options 访问参数
*/
public void getJokesByHttpResultMap(Subscriber<List<JuHeDream>> subscriber, Map<String, Object> options){
// juheService.getJokesByRxJavaHttpResult(options)
// .map(new HttpResultFunc<JuHeDream>())
// .subscribeOn(Schedulers.io())
// .unsubscribeOn(Schedulers.io())
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(subscriber);
Observable<List<JuHeDream>> observable = juheService.getDreams(options)
.map(new HttpResultFunc<List<JuHeDream>>());
toSubscribe(observable,subscriber); }
}

其中包含异常的处理

public class ApiException extends RuntimeException{
public final static int TIME_MUST_10=209501;
public final static int TIME_OTHER=209502; public ApiException(int resultCode) {
this(getApiExceptionMessage(resultCode));
} public ApiException(String detailMessage) {
super(detailMessage);
} /**
* 由于服务器传递过来的错误信息直接给用户看的话,用户未必能够理解
* 需要根据错误码对错误信息进行一个转换,在显示给用户
* @param code
* @return
*/
private static String getApiExceptionMessage(int code){
String message = "";
switch (code) {
case TIME_MUST_10:
message = "必须为10位时间戳";
break;
case TIME_OTHER:
message = "page、pagesize必须为int类型,time为10位时间戳";
break;
default:
message = "未知错误"; }
return message;
}
}

BaseMvp封装

请参考上篇文章 Android MVP 架构封装

Retrofit2+Rxjava+MVP实践

MvpView

public interface MvpView extends BaseView {
//ListView的初始化
void setListItem(List<JuHeDream> data);
//Toast 消息
void showMessage(String messgae);
}

MvpPresenter

public class MvpPresenter extends BasePresenter<MvpView> {
private Context mContext;
private Subscriber subscriber;
private List<JuHeDream> mDatas; public MvpPresenter(Context context) {
this.mContext = context;
} //获取数据
public void getData(String q) throws UnsupportedEncodingException {
if (q.isEmpty()) {
mView.showMessage("请输入解梦内容");
return;
}
mView.showLoading();
getDream(q);
} public void onItemClick(int position) { List<String> stringList = mDatas.get(position).getList(); StringBuffer sbf = new StringBuffer();
for (String s : stringList) {
sbf.append(s).append("\n\n\n");
}
new SweetAlertDialog(mContext)
.setTitleText(mDatas.get(position).getTitle())
.setContentText(sbf.toString())
.show();
} private void getDream(String q) throws UnsupportedEncodingException {
String content = URLDecoder.decode(q, "utf-8");
Map<String, Object> options = new HashMap<String, Object>();
options.put("key", "f86ed9f21931cd311deffada92b58ac7");
options.put("full", "1");
options.put("q", content); subscriber = new Subscriber<List<JuHeDream>>() { @Override
public void onCompleted() {
mView.hideLoading();
} @Override
public void onError(Throwable e) {
mView.hideLoading();
mView.showMessage(e.toString());
} @Override
public void onNext(List<JuHeDream> data) {
for (JuHeDream juheDream:data) {
Logger.e(juheDream.toString());
}
mDatas = data;
mView.setListItem(mDatas);
}
};
HttpJuHeMethods.getInstance().getJokesByHttpResultMap(subscriber,options);
} public void destory(){
subscriber.unsubscribe();
}
}

布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".view.MainActivity"> <LinearLayout
android:layout_width="920px"
android:layout_height="130px"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20px"
android:orientation="horizontal" > <LinearLayout
android:layout_width="680px"
android:layout_height="130px"
android:background="@drawable/shape_query_normal_stroke"
android:orientation="horizontal" > <ImageView
android:layout_width="57px"
android:layout_height="70px"
android:layout_gravity="center_vertical"
android:layout_marginLeft="40px"
android:src="@drawable/login_yanzhengma"
android:text="设置密码" /> <View
android:layout_width="0.5px"
android:layout_height="match_parent"
android:layout_marginLeft="40px"
android:background="@color/line" /> <EditText
android:id="@+id/id_dream_query"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginLeft="13px"
android:background="@null"
android:hint="请输入解梦的内容"
android:singleLine="true"
android:textColor="@color/textcolor"
android:textSize="40px" />
</LinearLayout> <View
android:layout_width="20px"
android:layout_height="match_parent" /> <Button
android:id="@+id/id_dream_btn"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:background="@drawable/query"
android:clickable="true"
android:gravity="center"
android:text="查询"
android:textColor="@android:color/white"
android:textSize="40px" />
</LinearLayout> <ListView
android:id="@+id/id_dream_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
/>
</LinearLayout>

MainActivity

public class MainActivity extends BaseMvpActivity<MvpView, MvpPresenter> implements MvpView, AdapterView.OnItemClickListener {

    @BindView(R.id.id_dream_query)
EditText dreamQuery;
@BindView(R.id.id_dream_btn)
Button dreamBtn;
@BindView(R.id.id_dream_result)
ListView listView; private Context mContext;
MyAdapter myAdapter; SweetAlertDialog pd; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
ButterKnife.bind(this);
initEvent();
} private void initEvent() {
listView.setOnItemClickListener(this);
} @OnClick(R.id.id_dream_btn)
public void onClick() {
try {
String q = dreamQuery.getText().toString();
presenter.getData(q);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} @Override
public MvpPresenter initPresenter() {
return new MvpPresenter(this);
} @Override
public void setListItem(List<JuHeDream> data) {
if (myAdapter == null){
myAdapter = new MyAdapter(mContext, data);
}
if (listView.getAdapter() == null){
listView.setAdapter(myAdapter);
}
myAdapter.refresh(data);
} @Override
public void showMessage(String messgae) {
Toast.makeText(mContext, messgae, Toast.LENGTH_SHORT).show();
} @Override
public void showLoading() {
if (pd == null) {
pd = new SweetAlertDialog(mContext, SweetAlertDialog.PROGRESS_TYPE);
pd.getProgressHelper().setBarColor(Color.parseColor("#A5DC86"));
pd.setTitleText("Loading");
pd.setCancelable(true);
}
pd.show();
} @Override
public void hideLoading() {
pd.hide();
} @Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
presenter.onItemClick(position);
} @Override
protected void onDestroy() {
presenter.destory();
super.onDestroy();
}
}

源码地址:https://github.com/Javen205/RxMVP

Retrofit2+Rxjava+MVP实践的更多相关文章

  1. Android使用RxJava+Retrofit2+Okhttp+MVP练习的APP

    Android使用RxJava+Retrofit2+Okhttp+MVP练习的APP 项目截图     这是我的目录结构 五步使用RxJava+Retrofit2+Okhttp+RxCache 第一步 ...

  2. Android 基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器aaa

    MDPlayer万能播放器 MDPlayer,基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器,可以播 ...

  3. MVP 实践

    今天有时间看了看google的官方文档,下载todo源码,仔细研读了一下,觉得其思想对开发还是有很大帮助的.个人认为,MVP通过Activity与业务逻辑的解耦,其作为Controller的职责更加单 ...

  4. Retrofit2+Rxjava+OkHttp的使用和网络请求

    Retrofit2+Rxjava+OkHttp的使用和网络请求 https://blog.csdn.net/huandroid/article/details/79883895 加入Rxjava 如果 ...

  5. RxJava操作符实践:8_算术和聚合操作之3_min

    发射原始Observable的最小值. Min操作符操作一个发射数值的Observable并发射单个值:最小的那个值. RxJava中,min属于rxjava-math模块. min接受一个可选参数, ...

  6. 一步步搭建Retrofit+RxJava+MVP网络请求框架(一)

    首先,展示一下封装好之后的项目的层级结构. 1.先创建一个RetrofitApiService.java package com.xdw.retrofitrxmvpdemo.http; import ...

  7. 一步步搭建Retrofit+RxJava+MVP网络请求框架(二),个人认为这次封装比较强大了

    在前面已经初步封装了一个MVP的网络请求框架,那只是个雏形,还有很多功能不完善,现在进一步进行封装.添加了网络请求时的等待框,retrofit中添加了日志打印拦截器,添加了token拦截器,并且对Da ...

  8. [Android] 转-RxJava+MVP+Retrofit+Dagger2+Okhttp大杂烩

    原文url: http://blog.iliyun.net/2016/11/20/%E6%A1%86%E6%9E%B6%E5%B0%81%E8%A3%85/ 这几年来android的网络请求技术层出不 ...

  9. retrofit2+rxjava+okhttp网络请求实现

    第一步:添加依赖: compile 'io.reactivex:rxandroid:1.2.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1. ...

随机推荐

  1. codevs 1005 生日礼物

    1005 生日礼物  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 9月12日是小松的朋友小寒的生日.小松知 ...

  2. AtCoder Grand Contest 019 F-yes or no

    AtCoder Grand Contest 019 F-yes or no 解题思路: 考虑一个贪心策略,假设当前还有 \(x\) 道 \(\text{yes}\) 和 \(y\) 道 \(\text ...

  3. bzoj 2961

    根据“点在圆内”关系,列出点P(x0,y0)在圆C(x,y)内的关系: (x-x0)^2+(y-y0)^2 <= x^2+y^2 化简得: 2*x0*x+2*y0*y >= x0^2+y0 ...

  4. wikioi 1294 全排列 dfs

    1294 全排列 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold       题目描述 Description 给出一个n, 请输出n的所有全排列 输入描述 Inpu ...

  5. Windows 7安装超级终端连接COM口设备

    Windows 7已经没有超级终端,只能用投机取巧的方式实现. 1.先配置电话 随便填写信息,然后点击确定即可. 2.下载这个终端运行,注意:要以管理员身份运行. 链接: https://pan.ba ...

  6. Accessing an element's parent with ElementTree(转)

    Today I ran across a situation where I needed to programmatically remove specific elements from a KM ...

  7. PHP-输入变量

    在Web开发过程中,我们经常需要获取系统变量或者用户提交的数据,这些变量数据错综复杂,而且一不小心就容易引起安全隐患,但是如果利用好ThinkPHP提供的变量获取功能,就可以轻松的获取和驾驭变量了. ...

  8. js判断手机端和pc端

    var browser = { versions: function() { var u = navigator.userAgent, app = navigator.appVersion; retu ...

  9. 报错:不允许保存更改。您所做的更改要求删除并重新创建以下表……

    在使用SQL Server 2008为某个表添加列的时候出现启用了"阻止保存要求重新创建表的更改问题的设置方法..."报错:   解决方法: 工具--选项--Designers-- ...

  10. pytest文档17-fixture之autouse=True

    前言 平常写自动化用例会写一些前置的fixture操作,用例需要用到就直接传该函数的参数名称就行了.当用例很多的时候,每次都传这个参数,会比较麻烦. fixture里面有个参数autouse,默认是F ...