RxJava结合Retrofit使用 自定义封装类结合泛型 请求网络数据+Fresco+RecyclerView+MVP分层

效果图:


效果图描述:

使用RxJava结合Retrofit,继承封装好的Activity与Presenter,使用MVP,请求网络数据;

使用Fresco加载图片,RecyclerView展示数据。


首先在项目Model的build.gradle里面导入依赖

//butterknife在Studio3.0版本上需使用以下8.8.1版本(下面2行代码都要加)
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

compile 'com.android.support:recyclerview-v7:26.+'  //(SDK版本需为26)

//rxjava2结合retrofit2
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.1.7'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'

compile 'com.facebook.fresco:fresco:1.5.0'

//由于Retrofit是基于OkHttp,所以还需要添加OkHttp库依赖
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
compile 'com.squareup.okhttp3:okhttp:3.9.0'
//如果采用了 Gson 解析,需要在 Gradle加入retrofit2类库中的gson依赖
compile 'com.squareup.retrofit2:converter-gson:2.3.0'   //较新版本

新建MyApplication 继承Application ,并在清单文件中配置

/**
 * 用于全局配置初始化异步加载类
 */
public class MyApplication extends Application {
    //设置公共变量
    public static GetDataInterface request;

    @Override
    public void onCreate() {
        super.onCreate();
        //1.  用于全局配置初始化Fresco 图片加载
        Fresco.initialize(this);

        //2.  用于全局配置初始化Retrofit 网络请求  RxJava结合Retrofit
        //构建Retrofit类,初始化参数
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://api.tianapi.com")
                .addConverterFactory(GsonConverterFactory.create())
                // call 转化成 Observerable
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        //创建网络请求接口实例
        request = retrofit.create(GetDataInterface.class);
    }
}
  1. <application  
  2.         android:name=".MyApplication" 

清单文件中加入权限

<uses-permission android:name="android.permission.INTERNET" />

请求网络获得的数据生成实体类

import java.util.List;

/**
 * http://api.tianapi.com/nba/?key=71e58b5b2f930eaf1f937407acde08fe&num=10
 */

public class Bean {

    /**
     * code : 200
     * msg : success
     * newslist : [{"ctime":"2016-12-04 13:00","title":"格林:理解科尔吸食大麻 不过我从没吸过","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161204/1-161204120131.jpg","url":"http://www.51tyw.com/nba/2421.html"},{"ctime":"2016-12-04 00:00","title":"三分纪录延续!火箭队连续19场比赛命中10+三分球","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161203/1-161203233J3.jpg","url":"http://www.51tyw.com/nba/2417.html"},{"ctime":"2016-12-04 00:00","title":"詹姆斯谈三连败:是时候紧起来了 必须打得男人点","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161203/1-161203234010.jpg","url":"http://www.51tyw.com/nba/2418.html"},{"ctime":"2016-12-03 12:00","title":"骑士输赢都靠三分?那还要詹姆斯做什么?","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161203/1-161203104344.jpg","url":"http://www.51tyw.com/nba/2407.html"},{"ctime":"2016-12-03 00:00","title":"公牛vs骑士直播看点:詹伟兄弟对决","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161202/1-161202221205.jpg","url":"http://www.51tyw.com/nba/2395.html"},{"ctime":"2016-12-02 22:00","title":"火箭和勇士联手创NBA三分纪录","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161202/1-161202214212.jpg","url":"http://www.51tyw.com/nba/2392.html"},{"ctime":"2016-12-02 22:00","title":"巴克利:勇士打得像女式篮球,太软了!","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161202/1-161202215032.jpg","url":"http://www.51tyw.com/nba/2394.html"},{"ctime":"2016-12-02 20:00","title":"詹姆斯完成月最佳球员4连霸的壮举!","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161202/1-1612021PI0.jpg","url":"http://www.51tyw.com/nba/2388.html"},{"ctime":"2016-12-01 00:00","title":"威少再下三双战书!詹皇会不会先认怂?","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161128/1-16112Q13251.jpg","url":"http://www.51tyw.com/nba/2374.html"},{"ctime":"2016-12-01 00:00","title":"骑士这样的防守想夺冠?也许卫冕只是空谈!","description":"NBA新闻","picUrl":"http://www.51tyw.com/uploads/allimg/161130/1-161130222229.jpg","url":"http://www.51tyw.com/nba/2375.html"}]
     */

    private int code;
    private String msg;
    private List newslist;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public List getNewslist() {
        return newslist;
    }

    public void setNewslist(List newslist) {
        this.newslist = newslist;
    }

    public static class NewslistBean {
        /**
         * ctime : 2016-12-04 13:00
         * title : 格林:理解科尔吸食大麻 不过我从没吸过
         * description : NBA新闻
         * picUrl : http://www.51tyw.com/uploads/allimg/161204/1-161204120131.jpg
         * url : http://www.51tyw.com/nba/2421.html
         */

        private String ctime;
        private String title;
        private String description;
        private String picUrl;
        private String url;

        public String getCtime() {
            return ctime;
        }

        public void setCtime(String ctime) {
            this.ctime = ctime;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public String getPicUrl() {
            return picUrl;
        }

        public void setPicUrl(String picUrl) {
            this.picUrl = picUrl;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }

    @Override
    public String toString() {
        return "Bean{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", newslist=" + newslist +
                '}';
    }
}

新建接口类GetDataInterface ,这里提供了get传参方法(@QueryMap注解

import bean.Bean;
import java.util.Map;
import io.reactivex.Observable;
import retrofit2.Call;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.QueryMap;

/**
 * 网络接口数据的请求类
 * 接口:APIKEY=‘71e58b5b2f930eaf1f937407acde08fe’
        http://api.tianapi.com/nba/?key=APIKEY&num=10
 */
public interface GetDataInterface {
    /*
     * 简单使用Retrofit的get请求数据 不传递参数
     */
    @GET("/nba/?key=18e883dd6b316eb1d97fd86338abbf06&num=10")
    Call get1();

    /**
     * 使用Retrofit的get请求数据,使用@QueryMap注解传递集合参数
     */
    @POST("/nba")
    Call get2(@QueryMap Map map);

    /**
     * 使用Retrofit的get请求数据,使用@QueryMap注解传递集合参数
     */
    @GET("/nba")
    Observable get(@QueryMap Map map);

    /**
     * 使用Retrofit的post请求数据,使用@FieldMap注解传递集合参数
     * 但是此接口不能使用post请求,因为该接口返回的数据只有get方式,所以下面的注解不能用(可以参照引用能用post方式的接口)
     */
    @FormUrlEncoded
    @POST("/nba")
    Observable post(@FieldMap Map map);
}

自定义Activity抽象类,持有View层和Presenter层

import android.app.Activity;
import android.os.Bundle;

/**
 * Activity抽象类,持有View层和Presenter层
 * @param   表示持有的View层
 * @param   表示持有的Presenter层
 */
public abstract class BaseMvpActivity<V,T extends BasePresenter<V>> extends Activity {

    //声明持有的p层
    public T p;

    public abstract T initPresenter();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_base_mvp);

        p = initPresenter();
    }

    //视图运行获取焦点时,连接view层
    @Override
    protected void onResume() {
        super.onResume();
        p.attach((V) this);
    }

    //试图销毁时释放内存
    @Override
    protected void onDestroy() {
        super.onDestroy();
        p.detach();
    }
}

自定义一个Presenter类,持有view层接口
/**
 * 自定义一个Presenter层,持有view层接口
 */
public class BasePresenter<V> {
    // V 相当于V的接口
    public V view;

    /**
     * 自定义Presenter 持有View 的接口
     * @param v
     */
    public void attach(V v){
        this.view = v;
    }

    /**
     * 自定义Presenter 释放持有View的接口, 防止内存泄漏
     */
    public void detach(){
        this.view = null;
    }
}

使用MVP三层编写数据

1.model层  

import java.util.HashMap;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

//model接口实现类
public class MyModel {
    /**
     * 简单使用Retrofit的get请求, 不传递参数
     * @param callBack
     */
    public void getData1(final ModelCallBack callBack){
        //设置接口请求的key值
        Call call = MyApplication.request.get1();

        //发起异步请求
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                //获取响应的数据
                Bean bean = response.body();

                //请求成功时返回数据
                callBack.onSuccess(bean);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                //请求失败时返回数据
                callBack.onFailure(new Exception(""));
            }
        });
    }

    /**
     * 简单使用Retrofit的get请求, 使用@QueryMap注解传递集合参数
     * @param callBack
     */
    public void getData2(final ModelCallBack callBack){
        //设置接口请求的集合参数
        HashMap map = new HashMap<>();
        map.put("key", "18e883dd6b316eb1d97fd86338abbf06");
        map.put("num", "10");

        Call call = MyApplication.request.get2(map);

        //发起异步请求
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                //获取响应的数据
                Bean bean = response.body();

                //请求成功时返回数据
                callBack.onSuccess(bean);
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                //请求失败时返回数据
                callBack.onFailure(new Exception(""));
            }
        });
    }


    /**
     * 使用Retrofit结合RxJava的get请求数据,使用@QueryMap注解传递集合参数
     * @param callBack
     */
    public void getData(final ModelCallBack callBack) {
        //设置接口请求的集合参数
        HashMap map = new HashMap<>();
        map.put("key", "18e883dd6b316eb1d97fd86338abbf06");
        map.put("num", "10");

        MyApplication.request.get(map)                      //获取Observable对象
                .subscribeOn(Schedulers.io())               //请求完成后在io线程中执行
                .observeOn(AndroidSchedulers.mainThread())  //最后在主线程中执行

                //进行事件的订阅,使用Consumer实现
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Bean bean) throws Exception {
                        //请求成功时返回数据
                        callBack.onSuccess(bean);
                        System.out.println(bean.toString());
                    }
                });
    }

}
model层接口

/**
 * model层接口,成功和失败的方法
 */
public interface ModelCallBack {
    public void onSuccess(Bean bean);
    public void onFailure(Exception e);
}
2.view层 

/**
 * view层接口类,请求成功与失败的方法
 */
public interface MyView {
    public void onSuccess(Bean bean);
    public void onFailure(Exception e);
}
3.presenter层  

// Presenter层,进行view层与model数据的交互

public class MyPresenter extends BasePresenter {
    private MyModel myModel;
    public MyPresenter() {
        this.myModel = new MyModel();
    }

    /**
     * 简单使用Retrofit的get请求, 不传递参数
     */
    public void get1(){
        myModel.getData1(new ModelCallBack() {
            @Override
            public void onSuccess(Bean bean) {
                //数据交互时,为防止内存泄露,设置view层数据为空
                if (view != null){
                    view.onSuccess(bean);
                }
            }

            @Override
            public void onFailure(Exception e) {
                //数据交互时,为防止内存泄露,设置view层数据为空
                if (view != null){
                    view.onFailure(new Exception("e"));
                }
            }
        });
    }

    /**
     * 简单使用Retrofit的get请求, 使用@QueryMap注解传递集合参数
     */
    public void get2(){
        myModel.getData2(new ModelCallBack() {
            @Override
            public void onSuccess(Bean bean) {
                //数据交互时,为防止内存泄露,设置view层数据为空
                if (view != null){
                    view.onSuccess(bean);
                }
            }

            @Override
            public void onFailure(Exception e) {
                //数据交互时,为防止内存泄露,设置view层数据为空
                if (view != null){
                    view.onFailure(new Exception("e"));
                }
            }
        });
    }

    /**
     * 简单使用Retrofit结合RxJava的get请求数据, 使用@QueryMap注解传递集合参数
     */
    public void get(){
        myModel.getData(new ModelCallBack() {
            @Override
            public void onSuccess(Bean bean) {
                //数据交互时,为防止内存泄露,设置view层数据为空
                if (view != null){
                    view.onSuccess(bean);
                }
            }

            @Override
            public void onFailure(Exception e) {
                //数据交互时,为防止内存泄露,设置view层数据为空
                if (view != null){
                    view.onFailure(new Exception("e"));
                }
            }
        });
    }

    //取消p层与v层的绑定,防止内存泄露
    @Override
    public void detach(){
        this.view = null;
    }
}

回调到view层MainActivity

//主页面继承自定义Activity,持有p与c层
public class MainActivity extends BaseMvpActivity implements MyView {
    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;
    private MyAdapter adapter;

    //声明presenter层,与view层交互
    @Override
    public MyPresenter initPresenter() {
        return new MyPresenter();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        //p层的get请求方式
//     p.get1();   //不传递参数
//     p.get2();   //只使用Retrofit的get请求数据,使用@QueryMap注解传递集合参数

        p.get();     //使用Retrofit+RxJava的get请求数据,使用@QueryMap注解传递集合参数
    }

    @Override
    public void onSuccess(Bean bean) {
        //设置布局管理器以及布局适配器
        LinearLayoutManager manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(manager);
        adapter = new MyAdapter(MainActivity.this);
        adapter.addData(bean);
        recyclerView.setAdapter(adapter);

        Toast.makeText(MainActivity.this,"数据:"+bean.toString(),Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFailure(Exception e) {
        System.out.println("数据出错:"+e);
    }
}
   

activity_main.xml

xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent">android.support.v7.widget.RecyclerView>


LinearLayout>
适配器MyAdapter

/**
 * //RecyclerView展示数据适配器
 */
public class MyAdapter extends RecyclerView.Adapter {
    private Context context;
    private List list;

    public MyAdapter(Context context) {
        this.context = context;
    }

    //声明数据来源,添加数据
    public void addData(Bean bean) {
        if (this.list == null) {
            this.list = new ArrayList<>();
        }
        this.list.addAll(bean.getNewslist());
        notifyDataSetChanged();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //创建视图
        View view = LayoutInflater.from(context).inflate(R.layout.adapter, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        //加载布局
        holder.draweeView.setImageURI(list.get(position).getPicUrl());
        holder.title.setText(list.get(position).getTitle());
    }

    @Override
    public int getItemCount() {
        return list == null ? 0: list.size();
    }

    static class MyViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.draweeView)
        SimpleDraweeView draweeView;
        @BindView(R.id.title)
        TextView title;
        public MyViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this,itemView);
        }
    }
}
adapter.xml

xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:padding="6dp"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <com.facebook.drawee.view.SimpleDraweeView
        android:id="@+id/draweeView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="6dp"
        fresco:placeholderImage="@drawable/app_default"
        fresco:placeholderImageScaleType="fitCenter"
        fresco:actualImageScaleType="focusCrop"
        fresco:failureImage="@drawable/load_error_image"
        fresco:failureImageScaleType="fitCenter"
        fresco:roundAsCircle="true"/>

    <TextView
        android:text="标题"
        android:id="@+id/title"
        android:textSize="18sp"
        android:textStyle="bold"
        android:layout_marginLeft="36dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"/>

LinearLayout>

Fresco加载图片的素材:

1. app_deafult.jpg



2. load_error_image.jpg

RxJava结合Retrofit使用 自定义封装类结合泛型 请求网络数据+Fresco+RecyclerView+MVP分层_第1张图片


你可能感兴趣的:(效果初现)