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; }}
- An_MVP_模式(okhttp)解析RecyclerView/XRecyclerView
- OkHttp+Xrecyclerview
- okHttp解析到RecyclerView显示
- XRecyclerview和Recyclerview详解
- MVP+OKhttp,拦截器+XRecyclerView+ImageLoader(Glide)
- 关于OkHttp解析数据添加到RecyclerView
- MVP模式OKhttp请求RecyclerView展示数据
- MVP模式的OKhttp请求网络数据,xrecyclerview上拉刷新,下拉加载
- okhttp+recyclerview
- okhttp+recyclerView
- RecyclerView okHttp
- XRecyclerview mvpgson网络解析
- Okhttp解析Gson数据并且展示到recyclerView
- OkHttp解析数据,RecyclerView和Glide的加载图片
- RecyclerView的多条目展示,使用OkHttp解析数据
- Okhttp解析Gson数据并且展示到recyclerView
- MVP+Rxjava+Okhttp+Retrofit+XRecyclerview请求数据
- OkHttp完全解析(一)OkHttp简介
- java.util.concurrent.TimeoutException: android.view.ThreadedRenderer.finalize() timed out after 10 s
- Oc GDataXML(DOM)解析分区表格
- ARM9 S3C2451 UART 理解
- Oc NSXMLParse(SAX)解析表格
- 编译caffe和matlab接口问题
- An_MVP_模式(okhttp)解析RecyclerView/XRecyclerView
- 多数据源配置spting-mybatis
- Oc NSXMLParse(SAX)解析分区表格
- echarts相关设置,看注释
- LeetCode 679: 24 Game 解题与思考
- 5
- Oc Json解析 表格
- 第八周项目二——顺序串算法
- 链表问题 删除链表的中间节点和a/b处的节点