使用MVP,OKHttp封装类及其拦截器,RecyclerView,SpringView,ImageLoader实现数据的多条目加载

来源:互联网 发布:C语言韩信点兵 编辑:程序博客网 时间:2024/05/29 16:31

1.  导包:gson包,ImageLoader包


2. 添加依赖:

(1)butterknife自动生成控件id和点击事件:

     compile 'com.jakewharton:butterknife:7.0.0'
(2)okhttp依赖:     compile 'com.squareup.okhttp3:okhttp:3.9.0'
(3)recyclerview依赖(我自己的版本需要把SDK改为25版本):

     compile 'com.android.support:recyclerview-v7:25.3.1'
     compile 'com.yqritc:recyclerview-flexibledivider:1.4.0'

(4)springview依赖

     compile 'com.liaoinstan.springview:library:1.3.0'

一 . 首先编写OKhttp的封装类

import java.io.File;import java.util.Map;import java.util.concurrent.TimeUnit;import okhttp3.FormBody;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;/** * Okhttp 单例 范型的封装 */public class OkhttpUtils {    private static OkhttpUtils okhttpUtils = null ;    private OkhttpUtils(){    }    public static OkhttpUtils getInstance(){        if(okhttpUtils == null){            okhttpUtils = new OkhttpUtils();            client = new OkHttpClient.Builder()                    .readTimeout(20, TimeUnit.SECONDS)                    .writeTimeout(20,TimeUnit.SECONDS)                    .connectTimeout(20,TimeUnit.SECONDS)                    .addInterceptor(new LoggingInterceptor())                    .build();        }        return okhttpUtils ;    }    private static OkHttpClient client ;    public void asy(Map<String,String> params,String url,AbstractUiCallBack callBack){        Request request = null ;        if(params != null){            FormBody.Builder builder = new FormBody.Builder() ;            for(Map.Entry<String,String> entry : params.entrySet()){                builder.add(entry.getKey(),entry.getValue());            }            FormBody body =  builder.build();            request = new Request.Builder()                    .url(url)                    .post(body)                    .build();        } else {            request = new Request.Builder()                    .url(url)                    .build();        }        client.newCall(request).enqueue(callBack);    }    private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");    public static void postFile(Map<String,String> map, String url, File file,AbstractUiCallBack callBack) {        String[] array = file.getAbsolutePath().split("\\/");        MultipartBody.Builder builder = new MultipartBody.Builder();        builder.setType(MultipartBody.FORM);        for (Map.Entry<String, String> entry : map.entrySet()) {            builder.addFormDataPart(entry.getKey(), entry.getValue());        }        builder.addFormDataPart("imageFileName", array[array.length - 1]);        if (file.exists() && file.length() > 0) {            builder.addFormDataPart("image", array[array.length - 1], RequestBody.create(MEDIA_TYPE_PNG, file));        }        MultipartBody body = builder.build();        Request request = new Request.Builder()                .url(url)                .post(body)                .build();        client.newCall(request).enqueue(callBack);    }}

   OKhttp封装需实现的接口类   

import android.os.Handler;import android.os.Looper;import com.google.gson.Gson;import com.google.gson.JsonSyntaxException;import java.io.IOException;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type;import okhttp3.Call;import okhttp3.Callback;import okhttp3.Response;/** *  * Okhttp 单例 范型的封装 */public  abstract  class AbstractUiCallBack<T> implements Callback {    /**     * 成功回调     * @param t     */    public abstract void success(T t);    /**     * 失败回调     * @param e     */    public abstract void failure(Exception e);    private Handler handler = null ;    private Class clazz ;    public AbstractUiCallBack(){        handler = new Handler(Looper.getMainLooper());        //  得到的是一个 AbstractUiCallBack<T> 的Type       Type type =  getClass().getGenericSuperclass() ;        // 得到的是T的实际Type       Type [] arr =  ((ParameterizedType)type).getActualTypeArguments() ;        clazz = (Class) arr[0] ;    }    @Override    public void onFailure(Call call, IOException e) {        failure(e);    }    @Override    public void onResponse(Call call, Response response) throws IOException {        try {            String result = response.body().string();            System.out.println("result = " + result);            Gson gson = new Gson();            final T t = (T) gson.fromJson(result,clazz);            handler.post(new Runnable() {                @Override                public void run() {                    success(t);                }            });        } catch (IOException e) {            e.printStackTrace();            failure(e);        } catch (JsonSyntaxException e) {            e.printStackTrace();            failure(e);        }    }}

二. 拦截器类

import java.io.IOException;import okhttp3.Interceptor;import okhttp3.Request;import okhttp3.Response;//拦截器类public class LoggingInterceptor implements Interceptor{    @Override    public Response intercept(Chain chain) throws IOException {        Request request = chain.request();  //请求对象        /**         * 返回最准确的可用系统计时器的当前值,以毫微秒为单位         * 返回值表示从某一固定但任意的时间算起的毫微秒数         */        long time1 = System.nanoTime();        Response response = chain.proceed(request);  //响应对象        long time2 = System.nanoTime();        System.out.println("响应时长 = "+(time2 - time1));        return response;    }}

三. model层

import com.bwie.secondweek.bean.MyDataBean;import com.bwie.secondweek.okhttp.AbstractUiCallBack;import com.bwie.secondweek.okhttp.OkhttpUtils;/** * model层,数据的存取 */public class DataModel {    //上拉刷新下拉加载更多    public void onRefresh(boolean b, final DataModelCallBack modelCallBack){        OkhttpUtils.getInstance().asy(null, "http://v.juhe.cn/toutiao/index?type=toutiao&key=c4479ad58f41e7f78a8fa073d0b1f1b5", new AbstractUiCallBack<MyDataBean>() {            @Override            public void success(MyDataBean dataBean) {                modelCallBack.success(dataBean);            }            @Override            public void failure(Exception e) {                modelCallBack.failure(e);            }        });    }    //定义接口    public interface DataModelCallBack{        public void success(MyDataBean dataBean);   //成功获取数据        public void failure(Exception e);            //数据获取失败    }}

四. view层

import com.bwie.secondweek.bean.MyDataBean;/** * view层,UI界面的搭建 */public interface DataView {    public void success(MyDataBean dataBean);   //成功获取数据    public void failure(Exception e);            //数据获取失败}

五. presenter层

import com.bwie.secondweek.bean.MyDataBean;import com.bwie.secondweek.model.DataModel;import com.bwie.secondweek.view.DataView;/** * presenter层,进行model和view层之间数据的交互 */public class DataPresenter {    private DataView dataView;    private DataModel dataModel;    //构造方法中声明view层,初始化model层数据    public DataPresenter(DataView dataView) {        this.dataView = dataView;        dataModel = new DataModel();    }    //调用model层接口,上拉加载下拉刷新    public void onRefresh(final boolean b){        dataModel.onRefresh(b, new DataModel.DataModelCallBack() {            @Override            public void success(MyDataBean dataBean) {                dataView.success(dataBean);            }            @Override            public void failure(Exception e) {                dataView.failure(e);            }        });    }}

六. imageloader工具类及其全局初始化配置

(1)全局初始化配置类:

package com.bwie.secondweek.util;import android.app.Application;//全局初始化Application类public class BaseApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        //配置imageLoader        ImageLoaderUtil.init(this);    }}

(2)imageloader工具类:

package com.bwie.secondweek.util;import android.content.Context;import android.graphics.Bitmap;import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiscCache;import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;import com.nostra13.universalimageloader.core.DisplayImageOptions;import com.nostra13.universalimageloader.core.ImageLoader;import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;import com.nostra13.universalimageloader.core.assist.ImageScaleType;import com.nostra13.universalimageloader.core.assist.QueueProcessingType;import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;import com.nostra13.universalimageloader.core.download.BaseImageDownloader;import com.nostra13.universalimageloader.utils.StorageUtils;import java.io.File;public class ImageLoaderUtil {    /**     * 初始化imageLoader     * @param context     */    public static void init(Context context) {        //1.获取配置config对象        File cacheDir = StorageUtils.getCacheDirectory(context);  //缓存文件夹路径        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)                .threadPoolSize(3) // default  线程池内加载的数量                .threadPriority(Thread.NORM_PRIORITY - 2) // default 设置当前线程的优先级                .tasksProcessingOrder(QueueProcessingType.FIFO) // default                .denyCacheImageMultipleSizesInMemory()                .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) //可以通过自己的内存缓存实现                .memoryCacheSize(2 * 1024 * 1024)  // 内存缓存的最大值                .memoryCacheSizePercentage(13) // default                .diskCache(new UnlimitedDiscCache(cacheDir)) // default 可以自定义缓存路径                .diskCacheSize(50 * 1024 * 1024) // 50 Mb sd卡(本地)缓存的最大值                .diskCacheFileCount(100)  // 可以缓存的文件数量                // default为使用HASHCODE对UIL进行加密命名, 还可以用MD5(new Md5FileNameGenerator())加密                .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())                .imageDownloader(new BaseImageDownloader(context)) // default                .imageDecoder(new BaseImageDecoder(true)) // default                .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // default                .writeDebugLogs() // 打印debug log                .build(); //开始构建        //2.初始化配置...ImageLoader.getInstance()图片加载器的对象,单例模式        ImageLoader.getInstance().init(config);    }    /**     * imageLoader加载图片的默认选项     * @return     */    public static DisplayImageOptions getDefaultOption(){        DisplayImageOptions options = new DisplayImageOptions.Builder()                .showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的默认图片                .showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片                .showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片                .resetViewBeforeLoading(true)  // default 设置图片在加载前是否重置、复位                .delayBeforeLoading(1000)  // 下载前的延迟时间                .cacheInMemory(true) // default  设置下载的图片是否缓存在内存中                .cacheOnDisk(true) // default  设置下载的图片是否缓存在SD卡中                .considerExifParams(true) // default                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示                .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型                .displayer(new SimpleBitmapDisplayer()) // default  还可以设置圆角图片new RoundedBitmapDisplayer(20)                .build();        return options;    }    /**     * imageLoader加载圆角图片....指定圆角的大小     * @return     */    public static DisplayImageOptions getRoundedOption(int corner){        DisplayImageOptions options = new DisplayImageOptions.Builder()                .showImageOnLoading(R.mipmap.ic_launcher) // 设置图片下载期间显示的图片                .showImageForEmptyUri(R.mipmap.ic_launcher) // 设置图片Uri为空或是错误的时候显示的图片                .showImageOnFail(R.mipmap.ic_launcher) // 设置图片加载或解码过程中发生错误显示的图片                .resetViewBeforeLoading(true)  // default 设置图片在加载前是否重置、复位                .delayBeforeLoading(1000)  // 下载前的延迟时间                .cacheInMemory(true) // default  设置下载的图片是否缓存在内存中                .cacheOnDisk(true) // default  设置下载的图片是否缓存在SD卡中                .considerExifParams(true) // default                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default 设置图片以如何的编码方式显示                .bitmapConfig(Bitmap.Config.RGB_565) // default 设置图片的解码类型                .displayer(new RoundedBitmapDisplayer(corner)) // default  还可以设置圆角图片new RoundedBitmapDisplayer(20)                .build();        return options;    }}

七. 数据接口封装的bean类(根据自己需要定义)

八. 主功能代码MainActivity

import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.widget.Toast;import com.bwie.secondweek.adapter.DataAdapter;import com.bwie.secondweek.bean.MyDataBean;import com.bwie.secondweek.presenter.DataPresenter;import com.bwie.secondweek.view.DataView;import com.liaoinstan.springview.container.DefaultFooter;import com.liaoinstan.springview.container.DefaultHeader;import com.liaoinstan.springview.widget.SpringView;import butterknife.Bind;import butterknife.ButterKnife;//主功能代码类,实现view层,进行数据UI的获取public class MainActivity extends AppCompatActivity implements DataView {    @Bind(R.id.recyclerView)    RecyclerView recyclerView;    @Bind(R.id.springview)    SpringView springview;    private DataPresenter dataPresenter;    private DataAdapter adapter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        //声明presenter层        dataPresenter = new DataPresenter(this);        //设置布局适配器,,,线性布局管理器        adapter = new DataAdapter(this);        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);        recyclerView.setLayoutManager(layoutManager);        recyclerView.setAdapter(adapter);        //设置SpringView进行多条目加载的头布局和尾布局        springview.setHeader(new DefaultHeader(this));        springview.setFooter(new DefaultFooter(this));        //设置SpringView的刷新监听事件        springview.setListener(new SpringView.OnFreshListener() {            @Override            public void onRefresh() {                dataPresenter.onRefresh(true);            }            @Override            public void onLoadmore() {                dataPresenter.onRefresh(false);            }        });        dataPresenter.onRefresh(true);  //设置一直刷新数据    }    @Override    public void success(MyDataBean dataBean) {        //只要有数据就一直加载        if (springview != null){            springview.onFinishFreshAndLoad();        }        adapter.addData(dataBean.getResult().getData());    }    @Override    public void failure(Exception e) {        runOnUiThread(new Runnable() {            @Override            public void run() {                Toast.makeText(MainActivity.this,"数据出错",Toast.LENGTH_SHORT).show();            }        });    }}

九. 自定义适配器类

import android.content.Context;import android.support.v7.widget.RecyclerView;import android.text.TextUtils;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import com.bwie.secondweek.R;import com.bwie.secondweek.bean.MyDataBean;import com.bwie.secondweek.util.ImageLoaderUtil;import com.nostra13.universalimageloader.core.ImageLoader;import java.util.ArrayList;import java.util.List;import butterknife.Bind;import butterknife.ButterKnife;/** * 条目布局适配器 */public class DataAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {    private Context context;    private List<MyDataBean.ResultBean.DataBean> list;    public DataAdapter(Context context) {        this.context = context;    }    //声明数据来源,添加数据    public void addData(List<MyDataBean.ResultBean.DataBean> list) {        if (this.list == null) {            this.list = new ArrayList<>();        }        this.list.addAll(list);        notifyDataSetChanged();    }    //创建条目布局    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        if (viewType == 0) {            View view01 = LayoutInflater.from(context).inflate(R.layout.item1, parent, false);            return new ViewHolder01(view01);        } else if (viewType == 1) {            View view02 = LayoutInflater.from(context).inflate(R.layout.item2, parent, false);            return new ViewHolder02(view02);        } else {            View view03 = LayoutInflater.from(context).inflate(R.layout.item3, parent, false);            return new ViewHolder03(view03);        }    }    //绑定数据    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        //判断加载布局的类型        if (holder instanceof ViewHolder01) {            ViewHolder01 holder01 = (ViewHolder01) holder;            ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s(), holder01.listItem1Imageview, ImageLoaderUtil.getDefaultOption());        } else if (holder instanceof ViewHolder02) {            ViewHolder02 holder02 = (ViewHolder02) holder;            ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s(), holder02.listItem2Imageview1, ImageLoaderUtil.getDefaultOption());            ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s02(), holder02.listItem2Imageview2, ImageLoaderUtil.getDefaultOption());        } else {            ViewHolder03 holder03 = (ViewHolder03) holder;            ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s(), holder03.listItem3Imageview1, ImageLoaderUtil.getDefaultOption());            ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s02(), holder03.listItem3Imageview2, ImageLoaderUtil.getDefaultOption());            ImageLoader.getInstance().displayImage(list.get(position).getThumbnail_pic_s03(), holder03.listItem3Imageview3, ImageLoaderUtil.getDefaultOption());        }    }    @Override    public int getItemViewType(int position) {        //判断布局类型,加载不同数据        if (!TextUtils.isEmpty(list.get(position).getThumbnail_pic_s03())) {            return 2;        }else if (!TextUtils.isEmpty(list.get(position).getThumbnail_pic_s02())) {            return 1;        }else {            return 0;        }    }    //首先加载三种图片布局    @Override    public int getItemCount() {        return list == null ? 0 : list.size();    }    static class ViewHolder01 extends RecyclerView.ViewHolder {        @Bind(R.id.list_item1_textview)        TextView listItem1Textview;        @Bind(R.id.list_item1_imageview)        ImageView listItem1Imageview;        ViewHolder01(View itemView) {            super(itemView);            ButterKnife.bind(this, itemView);        }    }    static class ViewHolder02 extends RecyclerView.ViewHolder {        @Bind(R.id.list_item2_textview)        TextView listItem2Textview;        @Bind(R.id.list_item2_imageview1)        ImageView listItem2Imageview1;        @Bind(R.id.list_item2_imageview2)        ImageView listItem2Imageview2;        ViewHolder02(View itemView) {            super(itemView);            ButterKnife.bind(this, itemView);        }    }    static class ViewHolder03 extends RecyclerView.ViewHolder {        @Bind(R.id.list_item3_textview)        TextView listItem3Textview;        @Bind(R.id.list_item3_imageview1)        ImageView listItem3Imageview1;        @Bind(R.id.list_item3_imageview2)        ImageView listItem3Imageview2;        @Bind(R.id.list_item3_imageview3)        ImageView listItem3Imageview3;        ViewHolder03(View itemView) {            super(itemView);            ButterKnife.bind(this, itemView);        }    }}

十. 页面布局

1. activity_main.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <com.liaoinstan.springview.widget.SpringView        android:id="@+id/springview"        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>    </com.liaoinstan.springview.widget.SpringView></RelativeLayout>

2. 条目一:

<?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="wrap_content"    android:orientation="vertical">    <ImageView        android:layout_gravity="center_horizontal"        android:id="@+id/list_item1_imageview"        android:layout_height="wrap_content"        android:layout_width="wrap_content"        android:layout_marginTop="18dp"        android:src="@mipmap/ic_launcher" /></LinearLayout>


3. 条目二:

<?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="wrap_content"    android:orientation="vertical">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="18dp"        android:orientation="horizontal">        <ImageView            android:id="@+id/list_item2_imageview1"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:src="@mipmap/ic_launcher" />        <ImageView            android:id="@+id/list_item2_imageview2"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:src="@mipmap/ic_launcher" />    </LinearLayout></LinearLayout>


4. 条目三:

<?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="wrap_content"    android:orientation="vertical">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="18dp"        android:orientation="horizontal">        <ImageView            android:id="@+id/list_item3_imageview1"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:src="@mipmap/ic_launcher" />        <ImageView            android:id="@+id/list_item3_imageview2"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:src="@mipmap/ic_launcher" />        <ImageView            android:id="@+id/list_item3_imageview3"            android:layout_width="0dp"            android:layout_height="wrap_content"            android:layout_weight="1"            android:src="@mipmap/ic_launcher" />    </LinearLayout></LinearLayout>

注:

最后在  清单文件中  AndroidManifest.xml中配置权限,全局配置imageloader类

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

android:name=".util.BaseApplication"


阅读全文
0 0