xRecyclerView+Retrofit+OkHttp+RxJava+Fresco+MVP结合应用

例:


技能要求:

1. 如上图,使用 MVP+xRecyclerView+Retrofit+OkHttp+RxJava   

接口:APIKEY=‘71e58b5b2f930eaf1f937407acde08fe

http://api.tianapi.com/nba/?key=APIKEY&num=10


实现思路

1. 主页面显示一个xRecycleveiw实现分页加载

2. Retrofit访问网络接口获取数据

3. 添加动态代理

4. Rxjava异步处理数据

5. 设置适配器,将数据列表传入适配器

6. 重写适配器的4个方法,并在显示视图的方法中做优化

7. 在构造方法中初始化Fresco并做配置

8. 配置图片的显示方式为圆形显示

9. 在适配器显示视图的方法中通过Fresco来显示图片

10.点击删除条目

添加依赖:
dependencies {
    compile 'io.reactivex:rxjava:1.3.4'
    compile 'io.reactivex:rxandroid:1.2.1'

    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
    compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0-beta4'
    compile 'com.squareup.okhttp3:okhttp:3.9.0'
    //compile project(':xrecyclerview')
    compile 'com.facebook.fresco:fresco:0.12.0'//fresco
    compile 'com.jcodecraeer:xrecyclerview:1.3.2'//xrecyclerview
}

加权限:

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


http://api.tianapi.com/nba/?key=APIKEY&num=10

public class JavaBean {
    /**
     * code : 200
     * msg : success
     * newslist : [{"APIKEY":"1554c051d8e3f9e205a4cd77ae3168eb","title":"[贴图]迷人的职业女性【20161109","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/11/201611091148413631-4761447.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7527597-0-1.html"},{"ctime":"2016-11-09 16:00","title":"水灵秀气 陆金佳Jessica 气质养眼私房大秀迷人美腿","description":"美女写真","picUrl":"http://m.xxxiao.com/wp-content/uploads/sites/3/2016/09/m.xxxiao.com_e9b1d07eb4eefb2de98e7e1f267a2aad-682x1024.jpg","url":"http://m.xxxiao.com/78896"},{"ctime":"2016-11-09 16:00","title":"邻家有女叫格格 [贴图] 20161109","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/14/201611091440404841-4761447.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7527869-0-1.html"},{"ctime":"2016-11-09 16:00","title":"演员何花清纯甜美知性诱惑","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/07/17/201611071717489781-2484647.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7524871-0-1.html"},{"ctime":"2016-11-09 20:00","title":"傲娇优雅 啊狸ali 清凉夏日女仆","description":"美女写真","picUrl":"http://m.xxxiao.com/wp-content/uploads/sites/3/2016/08/m.xxxiao.com_51b9d936d17a1be700847c24b793b24b-683x1024.jpg","url":"http://m.xxxiao.com/67756"},{"ctime":"2016-11-09 22:00","title":"带眼镜的女孩","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/21/20161109214852611-619336.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7528672-0-1.html"},{"ctime":"2016-11-09 22:00","title":"爱秀18 (杨若心Young 2016.11.9)","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/21/20161109210818721-5058976.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7528658-0-1.html"},{"ctime":"2016-11-09 22:00","title":"爱秀17 (余菲菲Faye2016.11.9)","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/21/201611092120006111-5058976.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7528657-0-1.html"},{"ctime":"2016-11-09 22:00","title":"丽柜 (Model 允儿2016.11.09)","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/21/2016110921290321-5058976.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7528654-0-1.html"},{"ctime":"2016-11-09 22:00","title":"美女明星蔡蝶","description":"华声美女","picUrl":"http://image.hnol.net/c/2016-11/09/20/201611092015092811-2228137.jpg","url":"http://bbs.voc.com.cn/mm/meinv-7528543-0-1.html"}]
     */
    private int code;
    private String msg;
    private List<NewslistBean> 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<NewslistBean> getNewslist() {
        return newslist;
    }
    public void setNewslist(List<NewslistBean> newslist) {
        this.newslist = newslist;
    }
    public static class NewslistBean {
        /**
         * ctime : 2016-11-09 14:00
         * title : [贴图]迷人的职业女性【20161109         * description : 华声美女
         * picUrl : http://image.hnol.net/c/2016-11/09/11/201611091148413631-4761447.jpg
         * url : http://bbs.voc.com.cn/mm/meinv-7527597-0-1.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;
        }
    }
}

MainActivity 主方法类:

public class MainActivity extends AppCompatActivity {
    private List<JavaBean.NewslistBean> list = new ArrayList<>();
    private int num=10;
    private NewsPresenter presenter;
    private MyAdapter adapter;
    private XRecyclerView xRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        xRecyclerView = (XRecyclerView) findViewById(R.id.rv);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //显示垂直滚动列表或水,VERTICAL平垂直的
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        xRecyclerView.setLayoutManager(layoutManager);
        Fresco.initialize(this);//Fresco初始化

        getData(num);//数据连接
        //设置下拉刷新和加载更多可执行,true
        xRecyclerView.setPullRefreshEnabled(true);
        xRecyclerView.setLoadingMoreEnabled(true);
        xRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);//下拉刷新
        xRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.Pacman);//上拉加载
        /**
         *设定下拉刷新和上拉加载监听
         */
        xRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
            //下拉刷新监听
            @Override
            public void onRefresh() {
                new Handler().postDelayed(new Runnable(){
                    public void run() {
                        num=10;
                        getData(num);
                        xRecyclerView.refreshComplete();
                    }
                }, 2000);
            }
            //上拉加载监听
            @Override
            public void onLoadMore() {
                new Handler().postDelayed(new Runnable(){
                    public void run() {
                        num+=10;
                        getData(num);
                        xRecyclerView.refreshComplete();
                    }
                }, 2000);
            }
        });
    }
    /**
     * 数据连接
     * http://api.tianapi.com/nba/?key=APIKEY&num=10
     */
    public void getData(int count){
        presenter = new NewsPresenter();
        presenter.getNews("APIKEY", count);
        presenter.attachView(new NewsView() {
            @Override
            public void success(List<JavaBean.NewslistBean> data) {
                list.clear();
                list.addAll(data);
                Log.i("zzz", "success: " + list.toString());
                if (adapter==null){
                    adapter = new MyAdapter(list, MainActivity.this);
                    xRecyclerView.setAdapter(adapter);
                }else {
                    adapter.notifyDataSetChanged();
                }
            }
            @Override
            public void failed(String e) {
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (presenter!=null){
            presenter.detachView();
        }
    }
}

activity_main  主方法类布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.jcodecraeer.xrecyclerview.XRecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>


NewsPresenter    类:(有做防止内存泄漏的操作)

public class NewsPresenter {
    private NewsView inv;
    private Subscription subscribe;

    public void attachView(NewsView inv){
        this.inv = inv;
    }
    public void getNews(String key,int num){
        Retrofit retrofit = RetrofitUtils.getInstance().getRetrofit();
        BlogService service = retrofit.create(BlogService.class);
        subscribe = service.getUrl(key, num)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<JavaBean>() {
                    @Override
                    public void call(JavaBean javaBean) {
                        List<JavaBean.NewslistBean> list = javaBean.getNewslist();
                        inv.success(list);
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        inv.failed(throwable.getMessage());
                    }
                });
    }
    public void detachView(){
        // Activity销毁的时候取消订阅时间,防止内存泄漏
        if (subscribe != null) {
            if (subscribe.isUnsubscribed()) {
                subscribe.unsubscribe();
            }
        }
        if (inv!=null){
            inv = null;
        }
    }
}


NewsView    接口:

public interface NewsView {
    void success(List<JavaBean.NewslistBean> data);
    void failed(String e);
}

RetrofitUtils    类:

public class RetrofitUtils {
    private static volatile RetrofitUtils instance;
    private Retrofit retrofit;

    private RetrofitUtils(){

    }
    private RetrofitUtils(String baseUrl){
        OkHttpClient client = new OkHttpClient();
        retrofit = new Retrofit.Builder()
                .client(client)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .baseUrl(baseUrl)
                .build();
    }
    public static RetrofitUtils getInstance(String baseUrl){
        if (instance==null){
            synchronized (RetrofitUtils.class){
                if (null==instance){
                    instance = new RetrofitUtils(baseUrl);
                }
            }
        }
        return instance;
    }
    http://api.tianapi.com/nba/?key=APIKEY&num=10
    public static RetrofitUtils getInstance(){
        if (null == instance){
            return  getInstance("http://api.tianapi.com/");
        }
        return instance;
    }
    public Retrofit getRetrofit(){
        return retrofit;
    }
}


BlogService   接口:

public interface BlogService {
    @GET("meinv/")
    Observable<JavaBean> getUrl(@Query("key") String key, @Query("num") int num);
}

MyAdapter  适配器类:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private List<JavaBean.NewslistBean> datas;
    private Context context;

    public MyAdapter(List<JavaBean.NewslistBean> datas, Context context) {
        this.datas = datas;
        this.context = context;
    }

    //创建新View,被LayoutManager所调用
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View view = View.inflate(context, R.layout.item, null);
        ViewHolder vh = new ViewHolder(view);
        return vh;
    }

    //将数据与界面进行绑定的操作
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {
        viewHolder.item_img.setImageURI(datas.get(position).getPicUrl()); //获取图片,Fresco
        viewHolder.mTextView.setText(datas.get(position).getTitle());

        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                /**
                 * 点击条目删除
                 */
                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                builder.setIcon(R.mipmap.ic_launcher);
                builder.setTitle("我是对话框");
                builder.setMessage("我是对话框的内容");
                builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(context, "点击了取消按钮", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                    }
                });
                builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(context, "点击了确定的按钮", Toast.LENGTH_SHORT).show();
                        dialog.dismiss();
                        //移除数据
                        datas.remove(position);
                        //条目刷新
                        notifyDataSetChanged();
                    }
                });
                AlertDialog dialog = builder.create();
                dialog.show();
            }
        });
    }

    //获取数据的数量
    @Override
    public int getItemCount() {
        return datas.size();
    }

    //自定义的ViewHolder,持有每个Item的的所有界面元素
    public static class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        private SimpleDraweeView item_img;//获取图片Fresco
        public ViewHolder(View view) {
            super(view);
            mTextView = (TextView) view.findViewById(R.id.text);
            item_img = view.findViewById(R.id.item_img);
        }
    }
}

item  适配器布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:fresco="http://schemas.android.com/apk/res-auto">
    <LinearLayout
        android:layout_gravity="center_horizontal"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:text="名称:"
            android:textSize="30dp"
            android:textColor="#000000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/text"
            android:textSize="25dp"
            android:textColor="#FF0000"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <com.facebook.drawee.view.SimpleDraweeView
        android:layout_gravity="center_horizontal"
        android:id="@+id/item_img"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        fresco:placeholderImage="@mipmap/ic_launcher"/>
</LinearLayout>


MyApp 类:(记得在清单文件中添加name)

public class MyApp  extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        //fresco的初始化
        Fresco.initialize(this);
    }
}

猜你喜欢

转载自blog.csdn.net/jun_tong/article/details/80677922