一、为什么要使用异步加载
- 1.还是Android单线程模型
- 2.耗时操作阻塞UI线程
二、异步加载最常用的两种方式
- 1.多线程/线程池
- 2.AsyncTask
主要步骤 |
---|
1.异步处理的一般方法 |
2.使用多线程进行异步加载 |
3.使用AsyncTask进行异步加载 |
4.异步加载的缓存与优化 |
主要思想
- 1.通过异步加载,避免阻塞UI线程
- 2.通过LruCache,将已下载图片放到内存中
- 3.判断ListView滑动状态,决定何时加载图片
- 4.不仅仅是ListView ,任何控件都可以使用异步加载
1.实现ListView图文混排
通过使用AsynacTask网络异步加载数据,获取Json数据。解析Json数据到List中,文艺重现BaseAdapter
实现网络异步访问:
/**
* 实现网络的异步访问
* @author Administrator
*
*/
class NewsAsyncTask extends AsyncTask<String,Void,List<NewBrean>>{
@Override
protected List<NewBrean> doInBackground(String... params) {
return getJsonData(params[0]); //请求网址
}
@Override
protected void onPostExecute(List<NewBrean> result) {
super.onPostExecute(result);
NewsAdapter adapter = new NewsAdapter(MainActivity.this,result, mListView);
mListView.setAdapter(adapter);
}
}
将url对应的JSON格式数据转换为我们所封装的NewsBean对象:
/**
* 将url对应的JSON格式数据转换为我们所封装的NewsBean对象
* @param url
* @return
*/
private List<NewBrean> getJsonData(String url) {
List<NewBrean> newsBeanList = new ArrayList<NewBrean>();
try {
String jsonString = readStream(new java.net.URL(url).openStream());
JSONObject jsonObject ;
NewBrean newsBean;
try {
jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("data");
for(int i =0; i<jsonArray.length(); i++) {
jsonObject = jsonArray.getJSONObject(i);
newsBean = new NewBrean();
newsBean.newsIconUrl = jsonObject.getString("picSmall");
newsBean.newsTitle = jsonObject.getString("name");
newsBean.newsContent = jsonObject.getString("description");
newsBeanList.add(newsBean);
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (MalformedURLException e) {
} catch (IOException e) {
e.printStackTrace();
}
return newsBeanList;
}
通过is解析网页返回的数据:
/**
* 通过is解析网页返回的数据
* @param is
* @return
*/
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;
}
NewsBean对象代码:
public String newsIconUrl;
public String newsTitle;
public String newsContent;
2.图片异步加载
通过URL获取Bitmap。使用多线程和AsyncTask异步加载图片两种方式。采用的LruCache缓存图片。
多线程加载图片:
public void showImageByThread(ImageView imageView,final String url) {
mImageView = imageView;
mUrl = url;
new Thread(){
@Override
public void run() {
super.run();
Bitmap bitmap = getBitmapFromURL(url);
Message message = Message.obtain();
message.obj = bitmap;
handler.sendMessage(message);
}
}.start();
}
通过URL获取Bitmap:
public Bitmap getBitmapFromURL(String urlString) {
Bitmap bitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
connection.disconnect();
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
UI图片效果实现代码:
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
if(mImageView.getTag().equals(mUrl)) {
mImageView.setImageBitmap((Bitmap)msg.obj);
}
};
};
AsyncTask方式异步加载图片:
public void showImageByAsyncTask(ImageView imageView, String url){
//从缓存中取出对应的图片
Bitmap bitmap = getBitmapFromCache(url);
//如果缓存中没有,那么必须去下载
if(bitmap == null ){
//new NewsAsyncTask(url).execute(url);
imageView.setImageResource(R.drawable.ic_launcher);
} else {
imageView.setImageBitmap(bitmap);
}
}
private class NewsAsyncTask extends AsyncTask<String,Void,Bitmap> {
// private ImageView mImageView;
private String mUrl;
public NewsAsyncTask(String url) {
//mImageView = imageView;
mUrl = url;
}
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
//从网络上获取图片
Bitmap bitmap = getBitmapFromURL(params[0]);
if(bitmap !=null) {
//将不在缓存的图片加入缓存
addBitmapToCache(url, bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
/*if(mImageView.getTag().equals(mUrl)) {
mImageView.setImageBitmap(result);
}*/
ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl);
if(imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTask.remove(this);
}
}
采用的LruCache缓存图片
public ImageLoader(ListView listview) {
mListView = listview;
mTask = new HashSet<NewsAsyncTask>();
//获取最大可用内存
int maxMemory = (int) Runtime.getRuntime().maxMemory();
int cacheSize = maxMemory / 4;
mCaches = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
//在每次存入缓存的时候调用
return value.getByteCount();
}
};
}
//从缓存中获取数据
public Bitmap getBitmapFromCache(String url) {
return mCaches.get(url);
}
//增加到缓存
public void addBitmapToCache(String url, Bitmap bitmap) {
if(getBitmapFromCache(url) == null ){
mCaches.put(url, bitmap);
}
}
取消异步加载:
public void cancelAllTasks() {
if(mTask != null) {
for(NewsAsyncTask task : mTask) {
task.cancel(false);
}
}
}
3. 滚动的高效优化
获取滚动起始数据、图片加载优化、滚动状态判断与处理 首次启动预加载。
获取滚动起始数据:
/**
* @param firstVisibleItem:第一个可见元素
* @param visibleItemCount 可见元素的总数
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
//第一次显示的时候调用
if(mFirstIn && visibleItemCount > 0) {
mImageLoader.loadImages(mStart, mEnd);
mFirstIn = false;
}
}
//滚动状态
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState == SCROLL_STATE_IDLE) {
//加载可见项
mImageLoader.loadImages(mStart, mEnd);
} else {
//停止任务
mImageLoader.cancelAllTasks();
}
}
滚动判断与处理
/**
* 用来加载从start 到end的所有图片
* @param start
* @param end
*/
public void loadImages(int start, int end) {
for(int i = start; i < end; i++) {
String url = NewsAdapter.URLS[i];
//从缓存中取出对应的图片
Bitmap bitmap = getBitmapFromCache(url);
//如果缓存中没有,那么必须去下载
if(bitmap == null ){
NewsAsyncTask task = new NewsAsyncTask(url);
task.execute(url);
mTask.add(task);
} else {
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
}
网友评论