此博文根据前面两篇文章 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. 4144: [AMPPZ2014]Petrol (多源最短路+最小生成树+启发式合并)

    4144: [AMPPZ2014]Petrol Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 752  Solved: 298[Submit][Sta ...

  2. 认识javascript中的作用域和上下文

    javascript中的作用域(scope)和上下文(context)是这门语言的独到之处,这部分归功于他们带来的灵活性.每个函数有不同的变量上下文和作用域.这些概念是javascript中一些强大的 ...

  3. Python168的学习笔记7

    关于多线程操作. 对于IO操作,如访问网站,写入磁盘这种需要时间等待响应的操作,多个cpu也几乎不能提高效率. 对于CPU密集型操作,如这个格式转换,可以通过多个cpu同时去进行. 但是对于pytho ...

  4. 【BZOJ-1194】潘多拉的盒子 拓扑排序 + DP

    1194: [HNOI2006]潘多拉的盒子 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 456  Solved: 215[Submit][Stat ...

  5. POJ 1654 Area 计算几何

    #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> usi ...

  6. 恢复二进制文件中的block符号表

    前篇博客中,使用 杨君的小黑屋 提供的工具恢复二进制文件的符号表,只恢复了函数的符号表,本篇讲述如何恢复block符号表,杨君的博客中使用IDA分析二进制文件,本篇则使用MacOS系统上体验也不错的H ...

  7. Oracle SP2-0640

    安装Oracle database 11g express edition后,使用自带的SQL命令行,执行 select 1 from dual; 报出错误:SP2-0640 未连接 解决方法:使用 ...

  8. ThinkPHP空操作和空控制器的处理

    所谓的空操作和空控制器,简而言之就是系统中不存在该方法或控制器,导致系统报错(本文版本3.2.3). 正确URL(测试环境):  http://oa.com/index.php/admin/publi ...

  9. sqlserver存储过程循环写法

    用游标,和WHILE可以遍历您的查询中的每一条记录并将要求的字段传给变量进行相应的处理==================DECLARE @A1 VARCHAR(10),@A2 VARCHAR(10) ...

  10. GDB 调试PYTHON

    http://www.cnblogs.com/dkblog/p/3806277.html