Retrofit2+Rxjava+MVP 实践

作者: Javen205 | 来源:发表于2016-08-27 20:40 被阅读922次

    此博文根据前面两篇文章 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 实践

      本文链接:https://www.haomeiwen.com/subject/xidtettx.html