异步加载——MVP
来源:互联网 发布:南方数据粘贴 编辑:程序博客网 时间:2024/06/09 19:55
通过学习MVP设计模式,想写一个小例子巩固一下。写个什么例子好呢?之前学习过慕课网的有关异步加载的视频,就把这个例子改编一下吧。
使用到的json数据网址是:http://www.imooc.com/api/teacher?type=4&num=30
效果图
项目目录图
思路图
- 根据当前滚动的状态变化异步加载图片
- 当滚动停止时加载当前可见的item对应的图片
- 当listview处于非停止状态时取消所有加载任务
- 第一次进入页面时由于listview的状态没有改变所以不加载图片,需要增加一个boolean类型isFirst标识,在onScroll方法中触发加载。
- 将加载的图片存到LruCache中,当加载的时候先从LruCache中获取,如果没有再加载。
V层
主布局文件activity_main
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.sjb.bupt.asynctaskdemo.view.activity.MainActivity" android:orientation="vertical"> <ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView></LinearLayout>
item布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_icon" android:layout_width="70dp" android:layout_height="70dp" android:src="@mipmap/ic_launcher"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingLeft="5dp" android:gravity="center" > <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#333" android:textSize="16sp" android:maxLines="1" android:text="标题"/> <TextView android:id="@+id/tv_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="12sp" android:maxLines="3" android:text="内容"/> </LinearLayout></LinearLayout>
接口IMainActivityView
P层与V层通信需要通过此接口
package com.sjb.bupt.asynctaskdemo.view;import android.graphics.Bitmap;import android.widget.ImageView;import com.sjb.bupt.asynctaskdemo.model.bean.NewsEntity;import java.util.List;/** * Created by sjb on 2017/7/5. */public interface IMainActivityView { /** * 显示listview的数据 * @param datas */ void showListView(List<NewsEntity> datas); /** * 获取listView数据失败是调用 */ void loadFailed(); /** * 显示异步加载的图片 * @param imageView * @param bitmap */ void showAsyncTaskImage(ImageView imageView, Bitmap bitmap);}
MainActivity
MainActivity实现接口IMainActivityView和接口 AbsListView.OnScrollListener来监听listview的滚动事件
package com.sjb.bupt.asynctaskdemo.view.activity;import android.graphics.Bitmap;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.widget.AbsListView;import android.widget.ImageView;import android.widget.ListView;import android.widget.Toast;import com.sjb.bupt.asynctaskdemo.R;import com.sjb.bupt.asynctaskdemo.adapter.MyAdapter;import com.sjb.bupt.asynctaskdemo.model.bean.NewsEntity;import com.sjb.bupt.asynctaskdemo.presenter.ImageLoadPresenter;import com.sjb.bupt.asynctaskdemo.presenter.LoadDataPresenter;import com.sjb.bupt.asynctaskdemo.view.IMainActivityView;import java.util.List;public class MainActivity extends AppCompatActivity implements IMainActivityView, AbsListView.OnScrollListener { private ListView lv; private MyAdapter myAdapter; private String url="http://www.imooc.com/api/teacher?type=4&num=30"; private LoadDataPresenter presenter;//加载数据的presenter private ImageLoadPresenter mImageLoadPresenter;//加载图片的presenter private int mVisibleStartItem,mVisibleEndItem;//需要加载图片listview中item的开始和结束 public static String[] URLS;//将数据中的图片URL存起来 private boolean isFirst=true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews();//初始化控件 initObjects();//初始化对象 initEvents();//初始化事件 loadDatas();//加载listView的数据 } private void initEvents() { lv.setOnScrollListener(this); } private void loadDatas() { presenter.getDatas(url); } private void initObjects() { presenter=new LoadDataPresenter(this); mImageLoadPresenter = new ImageLoadPresenter(this,lv); } private void initViews() { lv = (ListView) findViewById(R.id.lv); } @Override public void showListView(List<NewsEntity> datas) { URLS=new String[datas.size()]; for (int i=0;i<datas.size();i++) { URLS[i]=datas.get(i).getPicSmall(); } myAdapter=new MyAdapter(this,datas); lv.setAdapter(myAdapter); } @Override public void loadFailed() { Toast.makeText(this,"数据加载失败",Toast.LENGTH_SHORT).show(); } @Override public void showAsyncTaskImage(ImageView imageView, Bitmap bitmap) { imageView.setImageBitmap(bitmap); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) { //加载图片 mImageLoadPresenter.showImages(mVisibleStartItem, mVisibleEndItem); }else{ //停止加载 mImageLoadPresenter.cancelAllTask(); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { mVisibleStartItem=firstVisibleItem; mVisibleEndItem=firstVisibleItem+visibleItemCount; if (isFirst&&visibleItemCount>0) { mImageLoadPresenter.showImages(mVisibleStartItem,mVisibleEndItem); isFirst=false; } }}
adapter
listview的MyAdapter代码如下
package com.sjb.bupt.asynctaskdemo.adapter;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import com.sjb.bupt.asynctaskdemo.R;import com.sjb.bupt.asynctaskdemo.model.bean.NewsEntity;import java.util.List;/** * Created by sjb on 2017/7/5. */public class MyAdapter extends BaseAdapter { private List<NewsEntity> mDatas; private Context mContex; public MyAdapter(Context context, List<NewsEntity> datas){ this.mContex=context; this.mDatas=datas; } @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView==null){ convertView = LayoutInflater.from(mContex).inflate(R.layout.listview_item, parent, false); } MyViewHolder holder= MyViewHolder.getViewHolder(convertView); NewsEntity news = mDatas.get(position); holder.tv_title.setText(news.getName()); holder.tv_content.setText(news.getDescription()); holder.iv_icon.setImageResource(R.mipmap.ic_launcher); holder.iv_icon.setTag(news.getPicSmall()); return convertView; } static class MyViewHolder{ private ImageView iv_icon; private TextView tv_title; private TextView tv_content; private MyViewHolder(View convertView){ iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon); tv_title = (TextView) convertView.findViewById(R.id.tv_title); tv_content = (TextView) convertView.findViewById(R.id.tv_content); } public static MyViewHolder getViewHolder(View convertView){ MyViewHolder holder = (MyViewHolder) convertView.getTag(); if (holder == null) { holder= new MyViewHolder(convertView); convertView.setTag(holder); } return holder; } }}
P层
加载数据的LoadDataPresenter
package com.sjb.bupt.asynctaskdemo.presenter;import com.sjb.bupt.asynctaskdemo.model.GetNewsModelImpl;import com.sjb.bupt.asynctaskdemo.model.IGetNewsModel;import com.sjb.bupt.asynctaskdemo.model.bean.NewsEntity;import com.sjb.bupt.asynctaskdemo.view.IMainActivityView;import java.util.List;/** * Created by sjb on 2017/7/5. */public class LoadDataPresenter { private IGetNewsModel mIGetNewsModel; private IMainActivityView mIMainActivityView; public LoadDataPresenter(IMainActivityView iMainActivityView){ this.mIMainActivityView=iMainActivityView; mIGetNewsModel=new GetNewsModelImpl(); } public void getDatas(String url){ mIGetNewsModel.getNews(url, new IGetNewsModel.OnGetNewsListener() { @Override public void onSuccess(List<NewsEntity> newsEntities) { mIMainActivityView.showListView(newsEntities); } @Override public void onFailed() { mIMainActivityView.loadFailed(); } }); }}
异步加载图片的ImageLoadPresenter
package com.sjb.bupt.asynctaskdemo.presenter;import android.graphics.Bitmap;import android.widget.ImageView;import android.widget.ListView;import com.sjb.bupt.asynctaskdemo.view.activity.MainActivity;import com.sjb.bupt.asynctaskdemo.model.IImageLoadModel;import com.sjb.bupt.asynctaskdemo.model.ImageLoadModelImpl;import com.sjb.bupt.asynctaskdemo.view.IMainActivityView;/** * Created by sjb on 2017/7/6. */public class ImageLoadPresenter { private IMainActivityView mIMainActivityView; private IImageLoadModel mIImageLoadModel; private ListView mListView; public ImageLoadPresenter(IMainActivityView iMainActivityView, ListView listView){ this.mIMainActivityView=iMainActivityView; this.mListView=listView; mIImageLoadModel=new ImageLoadModelImpl(mListView); } public void showImages(int start,int end){ for (int i=start;i<end;i++) { mIImageLoadModel.loadImage(MainActivity.URLS[i], new IImageLoadModel.OnImageLoadListener() { @Override public void onSuccess(ImageView imageView, Bitmap bitmap) { mIMainActivityView.showAsyncTaskImage(imageView,bitmap); } @Override public void onFailed() { } }); } } public void cancelAllTask(){ mIImageLoadModel.cancelAllTask(); }}
M层
根据json数据格式写了两个实体类
DatasEntity
package com.sjb.bupt.asynctaskdemo.model.bean;import java.util.List;/** * Created by sjb on 2017/7/5. */public class DatasEntity { private String status; private List<NewsEntity> data; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public List<NewsEntity> getData() { return data; } public void setData(List<NewsEntity> data) { this.data = data; }}
NewsEntity
package com.sjb.bupt.asynctaskdemo.model.bean;/** * Created by sjb on 2017/7/5. */public class NewsEntity { private int id; private String name; private String picSmall; private String picBig; private String description; private int learner; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPicSmall() { return picSmall; } public void setPicSmall(String picSmall) { this.picSmall = picSmall; } public String getPicBig() { return picBig; } public void setPicBig(String picBig) { this.picBig = picBig; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public int getLearner() { return learner; } public void setLearner(int learner) { this.learner = learner; }}
获取数据的接口model
package com.sjb.bupt.asynctaskdemo.model;import com.sjb.bupt.asynctaskdemo.model.bean.NewsEntity;import java.util.List;/** * Created by sjb on 2017/7/5. */public interface IGetNewsModel { /** * 获取listview的数据 * @param url * @param listener */ void getNews(String url, GetNewsModelImpl.OnGetNewsListener listener); /** * 监听获取数据的回调接口 */ interface OnGetNewsListener { void onSuccess(List<NewsEntity> newsEntities); void onFailed(); }}
获取数据接口的实现类GetNewsModelImpl
package com.sjb.bupt.asynctaskdemo.model;import android.os.AsyncTask;import android.os.Handler;import com.google.gson.Gson;import com.sjb.bupt.asynctaskdemo.model.bean.DatasEntity;import com.sjb.bupt.asynctaskdemo.model.bean.NewsEntity;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.URL;import java.util.ArrayList;import java.util.List;/** * Created by sjb on 2017/7/5. */public class GetNewsModelImpl implements IGetNewsModel { private OnGetNewsListener mListener; private Handler myHandler = new Handler(); @Override public void getNews(String url,OnGetNewsListener listener) { this.mListener=listener; new NewsAsyncTask().execute(url); } private List<NewsEntity> getJsonDatas(String url) { List<NewsEntity> datas = new ArrayList<>(); try { String jsonResult = readStream(new URL(url).openStream()); Gson gson=new Gson(); DatasEntity datasEntity = gson.fromJson(jsonResult, DatasEntity.class); datas = datasEntity.getData(); } catch (Exception e) { myHandler.post(new Runnable() { @Override public void run() { mListener.onFailed(); } }); e.printStackTrace(); } return datas; } private String readStream(InputStream is) { InputStreamReader isr; String result = ""; try { String line = ""; isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null) { result += line; } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return result; } class NewsAsyncTask extends AsyncTask<String, Void, List<NewsEntity>> { @Override protected List<NewsEntity> doInBackground(String... params) { return getJsonDatas(params[0]); } @Override protected void onPostExecute(List<NewsEntity> newsEntities) { super.onPostExecute(newsEntities); if (newsEntities != null) { mListener.onSuccess(newsEntities); }else{ mListener.onFailed(); } } }}
加载图片的接口Model
package com.sjb.bupt.asynctaskdemo.model;import android.graphics.Bitmap;import android.widget.ImageView;/** * Created by sjb on 2017/7/6. */public interface IImageLoadModel { /** * 通过url获取bitmap * @param url * @return */ Bitmap getBitmapFromUrl(String url); /** * 加载图片 * @param url * @param listener */ void loadImage(String url,OnImageLoadListener listener); /** * 取消所有加载任务 */ void cancelAllTask(); /** * 图片加载回调接口 */ interface OnImageLoadListener{ void onSuccess(ImageView imageView, Bitmap bitmap); void onFailed(); }}
加载图片接口model的实现类ImageLoadModelImpl
package com.sjb.bupt.asynctaskdemo.model;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.AsyncTask;import android.util.Log;import android.util.LruCache;import android.widget.ImageView;import android.widget.ListView;import java.io.IOException;import java.io.InputStream;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.List;import static android.content.ContentValues.TAG;/** * Created by sjb on 2017/7/5. */public class ImageLoadModelImpl implements IImageLoadModel { LruCache<String, Bitmap> mCache; private OnImageLoadListener mListener; private ListView mListView; private List<ImageAsyncTask> tasks; public ImageLoadModelImpl(ListView listView) { this.mListView=listView; tasks = new ArrayList<>(); final int maxMemory = (int) Runtime.getRuntime().maxMemory(); Log.d(TAG, "ImageLoadModelImpl: " + maxMemory); mCache = new LruCache<String, Bitmap>(maxMemory / 4) { @Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getByteCount(); } }; } @Override public void loadImage(String url, OnImageLoadListener listener) { this.mListener = listener; ImageView imageView=(ImageView) mListView.findViewWithTag(url); Bitmap bitmap = getBitmapFromCache(url); if (bitmap != null) { mListener.onSuccess(imageView, bitmap); } else { ImageAsyncTask task = new ImageAsyncTask(imageView, url); tasks.add(task); task.execute(url); } } @Override public void cancelAllTask() { if (tasks.size() != 0) { for (ImageAsyncTask task : tasks) { task.cancel(false); } } } private void addBitmapToCache(String key, Bitmap bitmap) { if (getBitmapFromUrl(key) == null) { mCache.put(key, bitmap); } } private Bitmap getBitmapFromCache(String key) { return mCache.get(key); } @Override public Bitmap getBitmapFromUrl(String url) { Bitmap bitmap = null; HttpURLConnection connection = null; InputStream is = null; try { URL mUrl = new URL(url); connection = (HttpURLConnection) mUrl.openConnection(); is = connection.getInputStream(); bitmap = BitmapFactory.decodeStream(is); } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { e.printStackTrace(); } if (connection != null) { connection.disconnect(); } } return bitmap; } private class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> { private String url; private ImageView imageView; public ImageAsyncTask(ImageView imageView,String url) { this.url = url; this.imageView = imageView; } @Override protected Bitmap doInBackground(String... params) { return getBitmapFromUrl(params[0]); } @Override protected void onPostExecute(Bitmap bitmap) { super.onPostExecute(bitmap); if (imageView.getTag().equals(url)) { //将图片存到缓存中 if (bitmap != null) { addBitmapToCache(url, bitmap); } mListener.onSuccess(imageView, bitmap); } tasks.remove(this); } }}
结束
如有错误望指出,相互交流,谢谢!
阅读全文
0 0
- 异步加载——MVP
- android49——异步加载
- Android—Loader异步加载
- ExtJS——TreeGrid异步加载
- 页面优化——js异步加载
- UniversalImageLoader——异步加载图片
- Android——异步加载图片
- 行政区划三级联动—异步加载数据
- MVP模式—徐旸
- Mvp模式--xlistview上拉加载下拉刷新——桃先森_
- Android——MVP模式拦截器加载网络数据,点击跳转购物车
- MVP实现分页加载
- Android学习笔记————异步图片加载
- 关于ListView (1)——异步加载图片
- jqgrid——treegrid动态异步加载数据
- AsyncTask案例——异步加载ListView内容,包括优化
- zTree初体验(三)——异步加载
- 异步任务加载网络数据——AsyncTask使用
- Ionic 安装部署
- 二维码的使用
- 获取系统硬件信息
- [RK3288][Android6.0] WiFi之Autojoin对无线网络的选择机制
- spark集群环境与任务调参
- 异步加载——MVP
- Wireshark网络抓包(一)——数据包、着色规则和提示
- 日常充电之--PHP表单验证
- 七、C_base——函数
- Dedecms网站服务器如何搬家?
- [Leetcode] 273. Integer to English Words 解题报告
- 不选择使用Lucene的6大原因?
- Hadoop入门基础教程 Hadoop之完全分布式环境搭建
- 来自 Adobe 的用户体验专家 AEM 之:第三方包的部署