An_MVP_模式(okhttp)解析RecyclerView/XRecyclerView

运用MVP模式写(okhttp)解析json,数据传输到RecyclerView中
一、三个层Model,view,Presenter;
二、导入okhttp,okio,RecyclerView依赖;

compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.okio:okio:1.13.0'
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
   加入网络权限
   <uses-permission android:name="android.permission.INTERNET"/>

三、封装Adapter实现效果;
下面操作代码
Model
model:接口 IShowRecyclerViewModel

public interface IShowRecyclerViewModel {
    //type是起的int属性的变量,用来刷新;
    //Callback 在presenter层实例化
    void showData(int type,Callback callback);
}

model:类 ShowRecyclerViewModel

public class ShowRecyclerViewModel implements IShowRecyclerViewModel {

    @Override
    public void showData(int type,Callback callback) {
        OkHttpUtils.getInstance().doGet("http://www.yulin520.com/a2a/impressApi/news/mergeList?sign=C7548DE604BCB8A17592EFB9006F9265&pageSize=20&gender=2&ts=1871746850&page="+type+"",callback);
    }
}

下面补充的是okhttp的封装:
Okhttp的封装类:
OkHttpUtils类(get请求):

public class OkHttpUtils {
    private Handler handler=new Handler();
    public Handler getHandler(){
        return handler;
    }
    private static OkHttpUtils okHttpUtils=new OkHttpUtils();
    private OkHttpUtils(){};
    public static OkHttpUtils getInstance(){
        return okHttpUtils;
    }
    private OkHttpClient client;
    private void initOkHttpClient(){
        if(client==null){
            client=new OkHttpClient().newBuilder().build();
        }
    }
    public void doGet(String url, Callback callback){
        initOkHttpClient();
        Request request=new Request.Builder().url(url).build();
        Call call=client.newCall(request);
        call.enqueue(callback);
    }
}

Okhttp的封装类:
OnUiCallback类(get请求):

public abstract class OnUiCallback implements Callback {
    private Handler handler=OkHttpUtils.getInstance().getHandler();
    public abstract void onFailed(Call call,IOException e);
    public abstract void onSuccess(String result)throws IOException;

    @Override
    public void onFailure(final Call call, final IOException e) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                onFailure(call,e);
            }
        });
    }

    @Override
    public void onResponse(Call call, final Response response) throws IOException {
        final String result=response.body().string();
        handler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    onSuccess(result);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

View
View :接口 IShowRecyclerViewView

public interface ShowRecyclerViewView {
    void showRecyclerView(List<Max.DataBean> list);
    int getID();

}

Presenter
Presenter: 类 ShowRecyclerViewPresenter
Max.class是bean包下的json类

public class ShowRecyclerViewpresenter {
    IShowRecyclerViewModel model;
    ShowRecyclerViewView view;
    List<Max.DataBean> list;
    Context context;
    public  ShowRecyclerViewpresenter(Context context, ShowRecyclerViewView view){
        this.context=context;
        this.view=view;
        model=new ShowRecyclerViewModel();
    }
   public void showRecyclerView(){
       int type=view.getID();
       model.showData(type, new OnUiCallback() {
           @Override
           public void onFailed(Call call, IOException e) {

           }

           @Override
           public void onSuccess(String result) throws IOException {
               Gson gson=new Gson();
               Max max = gson.fromJson(result, Max.class);
               list=max.getData();
               Toast.makeText(context,list.toString(),Toast.LENGTH_SHORT).show();
               view.showRecyclerView(list);
           }
       });

    }
}

MainActivity:

public class MainActivity extends AppCompatActivity implements ShowRecyclerViewView{

    private RecyclerView mRv;
    int type=1;
    ShowRecyclerViewpresenter presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        presenter=new ShowRecyclerViewpresenter(this,this);
        presenter.showRecyclerView();

    }
    private void initView() {
        mRv = (RecyclerView) findViewById(R.id.rv);
        LinearLayoutManager layoutManager=new LinearLayoutManager(this);
        mRv.setLayoutManager(layoutManager);
        mRv.addItemDecoration(new DividerItemDecoration(MainActivity.this,DividerItemDecoration.VERTICAL));
    }

    @Override
    public void showRecyclerView(List<Max.DataBean> list) {
      MyAdapter myadapter=new MyAdapter(MainActivity.this,list);
        mRv.setAdapter(myadapter);
    }

    @Override
    public int getID() {
        return type;
    }

}

Adapter:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
    Context context;
    List<Max.DataBean> list;
    public MyAdapter (  Context context, List<Max.DataBean> list){
        this.context=context;
        this.list=list;
    }
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=View.inflate(context,R.layout.items,null);
        MyViewHolder holder=new MyViewHolder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        ImageLoader.getInstance().displayImage(list.get(position).getImg(),holder.ivhead);
        holder.tvage.setText(list.get(position).getUserAge()+"岁");
        holder.tvh.setText(list.get(position).getOccupation());
        holder.tvmessage.setText(list.get(position).getIntroduction());
    }

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

    class MyViewHolder extends RecyclerView.ViewHolder{
        TextView tvmessage;
        TextView tvage;
        TextView tvh;
        ImageView ivhead;
        public MyViewHolder(View itemView) {
            super(itemView);
            tvage=itemView.findViewById(R.id.tvage);
            tvh=itemView.findViewById(R.id.tvh);
            tvmessage=itemView.findViewById(R.id.tvmessage);
            ivhead=itemView.findViewById(R.id.ivhead);
        }
    }
}

最后我们用ImageLoader来加载网络获取的数据:
定义MyApp类:
在清单文件中别忘了加上
android:name=”.MyApp”

public class MyApp extends Application {
    ImageLoader imageLoader;
    @Override
    public void onCreate() {
        super.onCreate();
        File file = this.getCacheDir();

        DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.mipmap.ic_launcher) // 加载未完成时显示的自定义图片
                .showImageForEmptyUri(R.mipmap.ic_launcher) // 链接为空时的占位图
                .showImageOnFail(R.mipmap.ic_launcher_round) // 加载失败时显示自定义图片
                .resetViewBeforeLoading(false)  // 在加载前是否重置 view ,默认为false
                .delayBeforeLoading(1000)  //设置在开始加载前的延迟时间,单位为毫秒
                .cacheInMemory(true) // 是否启用内存缓存,默认为false
                .cacheOnDisk(true) // 是否启用磁盘缓存,默认为false
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // 图片的缩放类型
                .bitmapConfig(Bitmap.Config.ARGB_8888) // 图片的色彩格式
                .handler(new Handler()) // handler 对象,消息处理
                .build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
                this)
                // max width, max height,即保存的每个缓存文件的最大长宽
                .memoryCacheExtraOptions(480, 800)
                // 线程池内加载的数量
                .threadPoolSize(3)
                // 线程优先级
                .threadPriority(Thread.NORM_PRIORITY - 2)
                .defaultDisplayImageOptions(options)
                // You can pass your own memory cache implementation你可以通过自己的内存缓存实现
                // .memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024))
                // .memoryCacheSize(2 * 1024 * 1024)
                //硬盘缓存50MB
                .diskCacheSize(50 * 1024 * 1024)
                //将保存的时候的URI名称用MD5
                .diskCacheFileNameGenerator(new Md5FileNameGenerator())
                // 加密
                .diskCacheFileNameGenerator(new HashCodeFileNameGenerator())//将保存的时候的URI名称用HASHCODE加密
                .tasksProcessingOrder(QueueProcessingType.LIFO)
                .diskCacheFileCount(100) //缓存的File数量
                .diskCache(new UnlimitedDiscCache(file))// 自定义缓存路径
                // .defaultDisplayImageOptions(DisplayImageOptions.createSimple())
                // .imageDownloader(new BaseImageDownloader(context, 5 * 1000,
                // 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间
                .writeDebugLogs() // Remove for release app
                .build();

        ImageLoader.getInstance().init(config);
    }

}

下面分享一个RecyclerView多条目加载的AdapterDemo(MVC):
加载一个头布局

private void initrvData() {
        myadapter=new MyRVAdapter();
        mXrv.setAdapter(myadapter);
        TextView title = new TextView(MainActivity.this);
        myadapter.addHeader(title);

    }


 class MyRVAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
        public static final int TYPE_HEADER = 0;
        public static final int TYPE_BO = 1;
        List<View> list = new ArrayList<>();

        public void addHeader(View view) {
            list.add(view);
        }
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            if (viewType == TYPE_HEADER) {
                View view = View.inflate(MainActivity.this, R.layout.xrvhead, null);
                MyHeaderHolder headerHolder = new MyHeaderHolder(view);
                return headerHolder;
            } else {
                View view = View.inflate(MainActivity.this, R.layout.xrvitem, null);
                MyViewHolder holder = new MyViewHolder(view);
                return holder;
            }
        }
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if (holder instanceof MyHeaderHolder) {
                ((MyHeaderHolder) holder).h_title.setText(m.getBillboard().getName());
                ((MyHeaderHolder) holder).h_name.setText(m.getBillboard().getUpdate_date());
                ((MyHeaderHolder) holder).h_info.setText(m.getBillboard().getComment());
                ImageLoader.getInstance().displayImage(m.getBillboard().getPic_s210(), ((MyHeaderHolder) holder).h_iv);
            }

            if (holder instanceof MyViewHolder) {
                ((MyViewHolder) holder).title.setText(listrv.get(position).getTitle());
                ((MyViewHolder) holder).author.setText(listrv.get(position).getAuthor());
                ((MyViewHolder) holder).name.setText(listrv.get(position).getAlbum_title());
                ImageLoader.getInstance().displayImage(listrv.get(position).getPic_big(), ((MyViewHolder) holder).iv);
            }
        }
        @Override
        public int getItemCount() {
            return listrv == null ? 0 : listrv.size();
        }


        @Override
        public int getItemViewType(int position) {
            if (position < list.size()) {
                return TYPE_HEADER;
            } else {
                return TYPE_BO;
            }
        }

        class MyHeaderHolder extends RecyclerView.ViewHolder {

            TextView h_title, h_name, h_info, h_author;
            ImageView h_iv;
            RelativeLayout rl;

            public MyHeaderHolder(View itemView) {
                super(itemView);
                h_iv = itemView.findViewById(R.id.header_iv);
                h_title = itemView.findViewById(R.id.header_title);
                h_author = itemView.findViewById(R.id.header_author);
                h_name = itemView.findViewById(R.id.header_name);
                h_info = itemView.findViewById(R.id.header_info);
                rl = itemView.findViewById(R.id.rl);
            }
        }

        class MyViewHolder extends RecyclerView.ViewHolder {

            TextView title, name, author;
            ImageView iv;


            public MyViewHolder(View itemView) {
                super(itemView);

                title = itemView.findViewById(R.id.title);
                name = itemView.findViewById(R.id.name);
                iv = itemView.findViewById(R.id.iv);
                author = itemView.findViewById(R.id.author);
            }
        }
    }

定义全局异常捕获处理器;
演示空指针异常时使用全局异常捕获处理器提示错误信息;
将错误日志成功保存到sd卡;
封装class CrashHandler.class 和CrashApplication.class

package com.example.login_recyclerview20171023;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


public class CrashHandler implements Thread.UncaughtExceptionHandler {
    public  static  final  String TAG="CrashHandler";
    //系统默认的UncaughtException处理类
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //系统默认的UncaughtException处理类
    private  static  CrashHandler INSTANCE=new CrashHandler();
    //程序的Context对象
    private Context mContext;
    //用来存储设备信息和异常信息
    private Map<String, String> infos = new HashMap<String, String>();

    //用于格式化日期,作为日志文件名的一部分

    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

    /** 保证只有一个CrashHandler实例 */
    private CrashHandler() {
    }

    /** 获取CrashHandler实例 ,单例模式 */
    public static CrashHandler getInstance() {
        return INSTANCE;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context;
        //获取系统默认的UncaughtException处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }
    /**
     * 当UncaughtException发生时会转入该函数来处理
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {

        if (!handleException(ex) && mDefaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            mDefaultHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }
            //退出程序
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }
    /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     *
     * @param ex
     * @return true:如果处理了该异常信息;否则返回false.
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        //使用Toast来显示异常信息
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();
        //收集设备参数信息
        collectDeviceInfo(mContext);
        //保存日志文件
        saveCrashInfo2File(ex);
        return true;
    }



    private void collectDeviceInfo(Context ctx) {


        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = null;
            pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }


        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

    /**
     * 保存错误信息到文件中
     *
     * @param ex
     * @return  返回文件名称,便于将文件传送到服务器
     */
    private String saveCrashInfo2File(Throwable ex) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }

        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = "crash-" + time + "-" + timestamp + ".log";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = "/sdcard/crash/";
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(sb.toString().getBytes());
                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }

    /**
     * 网络是否可用
     *
     * @param context
     * @return
     */
    public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo[] info = mgr.getAllNetworkInfo();
        if (info != null) {
            for (int i = 0; i < info.length; i++) {
                if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                    return true;
                }
            }
        }
        return false;
    }
}
public class CrashApplication extends Application {
    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        this.mContext = this;
        CrashHandler.getInstance().init(this);
    }

}

清单文件里配置name******
下面补充一个Xrecyclerview的 实例:
添加依赖:compile ‘com.jcodecraeer:xrecyclerview:1.3.2’
与recyclerview类似 不同的是可以实现下拉加载和上拉刷新功能:
MVP的model层:
接口 IShowXrecyclerViewp1 :

public interface IShowXrecyclerViewp1 {
    void showData(int type,Callback callback);
}

model类

public class ShowXrecyclerViewp1 implements IShowXrecyclerViewp1 {
    @Override
    public void showData(int type,Callback callback) {
        OkHttpUtils.getInstance().doGet("http://news-at.zhihu.com/api/4/news/before/"+type+"",callback);

    }
}

view层:

public interface bannerview {
   void getXrecyclerViewData(List<XrecyclerViewp1Bean.StoriesBean> listx);
    int getID();
}

presenter层:

public class XrecyclerViewp1Presenter  {
    Context context;
    IShowXrecyclerViewp1 model;
    bannerview view;
    private List<XrecyclerViewp1Bean.StoriesBean> listx;
    public XrecyclerViewp1Presenter(Context context,bannerview view){
        this.context=context;
        this.view=view;
        model=new ShowXrecyclerViewp1();

    }
    public void showXrecyclerViewData(){
        int type=view.getID();
       model.showData(type, new OnUiCallback() {
           @Override
           public void onFailed(Call call, IOException e) {

           }

           @Override
           public void onSuccess(String result) throws IOException {
                       Gson gson = new Gson();
                       XrecyclerViewp1Bean x = gson.fromJson(result, XrecyclerViewp1Bean.class);
                       listx=x.getStories();
                       view.getXrecyclerViewData(listx);
           }
       });
    }
}

看看它的adapter类:

public class XrecyclerViewp4adapter extends XRecyclerView.Adapter<XrecyclerViewp4adapter.MyViewHolder>  {
    Context context;
    List<RecyclerViewp4Bean.OthersBean> listg;
    public XrecyclerViewp4adapter(Context context,List<RecyclerViewp4Bean.OthersBean> listg){
        this.context=context;
        this.listg=listg;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view=View.inflate(context,R.layout.grideitem,null);
        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.tvp4.setText(listg.get(position).getName());
        ImageLoader.getInstance().displayImage(listg.get(position).getThumbnail(),holder.ivp4);
    }

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

    class MyViewHolder extends XRecyclerView.ViewHolder{
        ImageView ivp4;
        TextView tvp4;
        public MyViewHolder(View itemView) {
            super(itemView);
            tvp4=itemView.findViewById(R.id.tvg);
            ivp4=itemView.findViewById(R.id.ivg);
        }
    }
}

最后在fragment里面实现—showData()方法是刷新功能:

public class Fragmentzxrb extends Fragment implements bannerview {
    View view;
    private ViewPager mVprb;
    Banner bb;
    bannerpresenter presenter;
    XrecyclerViewp1Adapter xrecyclerViewp1Adapter;
    XrecyclerViewp1Presenter presenterx;
    List<String> listm;
    XRecyclerView rv;
    int type=20131119;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = View.inflate(getActivity(), R.layout.fragmentzxrb, null);
        initView();
        presenter=new bannerpresenter(getActivity(),this);
        presenterx=new XrecyclerViewp1Presenter(getActivity(),this);
        presenter.showbanner();
        presenterx.showXrecyclerViewData();
        showData();
        return view;
    }

    private void showData() {
        rv.setLoadingListener(new XRecyclerView.LoadingListener() {
            @Override
            public void onRefresh() {
                type++;
                presenterx.showXrecyclerViewData();
                xrecyclerViewp1Adapter.notifyDataSetChanged();
                rv.refreshComplete();
            }

            @Override
            public void onLoadMore() {
                type++;
                presenterx.showXrecyclerViewData();
                xrecyclerViewp1Adapter.notifyDataSetChanged();
                rv.refreshComplete();
            }
        });
    }

    private void initView() {
       rv=view.findViewById(R.id.rv);
        LinearLayoutManager layoutManager=new LinearLayoutManager(getActivity());
        rv.setLayoutManager(layoutManager);
        rv.addItemDecoration(new DividerItemDecoration(getActivity(),DividerItemDecoration.VERTICAL));
        bb=view.findViewById(R.id.bb);
        listm=new ArrayList<>();
    }

    @Override
    public void getbannerData(List<BannerBean.TopStoriesBean> listb) {
        for(int i=0;i<listb.size();i++){
            listm.add(listb.get(i).getImage());
        }
        bb.setImageLoader(new ImageLoaderBanner());
        bb.setImages(listm);
        bb.start();
    }

    @Override
    public void getXrecyclerViewData(List<XrecyclerViewp1Bean.StoriesBean> listx) {
        xrecyclerViewp1Adapter = new XrecyclerViewp1Adapter(getActivity(), listx);
        rv.setAdapter(xrecyclerViewp1Adapter);
    }

    @Override
    public int getID() {
        return type;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值