An_MVP_模式(okhttp)解析RecyclerView/XRecyclerView

来源:互联网 发布:飞秋for mac 编辑:程序博客网 时间:2024/06/05 16:11

运用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;    }}
原创粉丝点击