Android进阶:ListView性能优化异步加载图片 使滑动效果流畅
ListView 是一种可以显示一系列项目并能进行滚动显示的 View,每一行的Item可能包含复杂的结构,可能会从网络上获取icon等的一些图标信息,就现在的网络速度要想保持ListView运行的很好滚动流畅是做不到的
所以这里就需要把这些信息利用多线程实现异步加载
实现这样功能的类
- public class AsyncImageLoader {
- private HashMap<String, SoftReference<Drawable>> imageCache;
- public AsyncImageLoader() {
- imageCache = new HashMap<String, SoftReference<Drawable>>();
- }
- public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {
- if (imageCache.containsKey(imageUrl)) {
- SoftReference<Drawable> softReference = imageCache.get(imageUrl);
- Drawable drawable = softReference.get();
- if (drawable != null) {
- return drawable;
- }
- }
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
- }
- };
- new Thread() {
- @Override
- public void run() {
- Drawable drawable = loadImageFromUrl(imageUrl);
- imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
- Message message = handler.obtainMessage(0, drawable);
- handler.sendMessage(message);
- }
- }.start();
- return null;
- }
- public static Drawable loadImageFromUrl(String url) {
- // ...
- }
- public interface ImageCallback {
- public void imageLoaded(Drawable imageDrawable, String imageUrl);
- }
- }
注意这里使用了 SoftReference来缓存图片,允许 GC在需要的时候可以对缓存中的图片进行清理。它这样工作:
· 调用 loadDrawable(ImageUrl, imageCallback),传入一个匿名实现的 ImageCallback接口
· 如果图片在缓存中不存在的话,图片将从单一的线程中下载并在下载结束时通过 ImageCallback回调
· 如果图片确实存在于缓存中,就会马上返回,不会回调 ImageCallback
然后我们还可以根据09google I/0开发者大会提到的方式来继续优化Adapter 使用ViewHolder来减少一些比较费时的操作,譬如inflate XML 和 findViewById()等操作
- public class ImageAndTextListAdapter extends ArrayAdapter<ImageAndText> {
- private ListView listView;
- private AsyncImageLoader asyncImageLoader;
- public ImageAndTextListAdapter(Activity activity, List<ImageAndText> imageAndTexts, ListView listView) {
- super(activity, 0, imageAndTexts);
- this.listView = listView;
- asyncImageLoader = new AsyncImageLoader();
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- Activity activity = (Activity) getContext();
- // Inflate the views from XML
- View rowView = convertView;
- ViewCache viewCache;
- if (rowView == null) {
- LayoutInflater inflater = activity.getLayoutInflater();
- rowView = inflater.inflate(R.layout.image_and_text_row, null);
- viewCache = new ViewCache(rowView);
- rowView.setTag(viewCache);
- } else {
- viewCache = (ViewCache) rowView.getTag();
- }
- ImageAndText imageAndText = getItem(position);
- // Load the image and set it on the ImageView
- String imageUrl = imageAndText.getImageUrl();
- ImageView imageView = viewCache.getImageView();
- imageView.setTag(imageUrl);
- Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {
- public void imageLoaded(Drawable imageDrawable, String imageUrl) {
- ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
- if (imageViewByTag != null) {
- imageViewByTag.setImageDrawable(imageDrawable);
- }
- }
- });
- imageView.setImageDrawable(cachedImage);
- // Set the text on the TextView
- TextView textView = viewCache.getTextView();
- textView.setText(imageAndText.getText());
- return rowView;
- }
- }
这里我们没有加载完iamge之后直接设定到相应的ImageView上 ,而是通过Tag查找,这里我们重用的View 这里有个listView的引用来通过Tag查找 可见 CallBack的实现
- ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);
- if (imageViewByTag != null) {
- imageViewByTag.setImageDrawable(imageDrawable);
- }
这里通过ViewCatch来减少了 findViewById的使用
- public class ViewCache {
- private View baseView;
- private TextView textView;
- private ImageView imageView;
- public ViewCache(View baseView) {
- this.baseView = baseView;
- }
- public TextView getTextView() {
- if (textView == null) {
- textView = (TextView) baseView.findViewById(R.id.text);
- }
- return titleView;
- }
- public ImageView getImageView() {
- if (imageView == null) {
- imageView = (ImageView) baseView.findViewById(R.id.image);
- }
- return imageView;
- }
- }
总结 :这里主要做了三点优化
- 在单一线程里加载图片
- 重用列表中行
- 缓存行中的 View
转自:http://blog.csdn.net/wanglong0537/article/details/6334005
Android进阶:ListView性能优化异步加载图片 使滑动效果流畅的更多相关文章
- 【Android】ListView、RecyclerView异步加载图片引起错位问题
今天在RecyclerView列表里遇到一个情况,它包含300条数据,每项包含一个图片,发现在首次载入时,由于本地没图,请求网络的时候:快速滑动导致了图片错位.闪烁的问题. 原理的话有一篇已经说的很清 ...
- ListView与GridView异步加载图片
原理很简单,主要是用到了回调方法,下面是异步加载图片的类 <span style="font-size:16px;">package com.xxx.xxx; impo ...
- 又优化了一下 Android ListView 异步加载图片
写这篇文章并不是教大家怎么样用listview异步加载图片,因为这样的文章在网上已经有很多了,比如这位仁兄写的就很好: http://www.iteye.com/topic/685986 我也是因为看 ...
- Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案
我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如L ...
- Android之ListView异步加载图片且仅显示可见子项中的图片
折腾了好多天,遇到 N 多让人崩溃无语的问题,不过今天终于有些收获了,这是实验的第一版,有些混乱,下一步进行改造细分,先把代码记录在这儿吧. 网上查了很多资料,发现都千篇一律,抄来抄去,很多细节和完整 ...
- Android的ListView异步加载图片时,错位、重复、闪烁问题的分析及解决方法
Android ListView异步加载图片错位.重复.闪烁分析以及解决方案,具体问题分析以及解决方案请看下文. 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图 ...
- Listview 异步加载图片之优化篇(有图有码有解释)
在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...
- android Listview 软引用SoftReference异步加载图片
首先说一下,android系统加载大量图片系统内存溢出的3中解决方法: (1)从网络或本地加载图片的时候,只加载缩略图.这个方法的确能够少占用不少内存,可是它的致命的缺点就是,因为加载的是缩略图,所以 ...
- Listview异步加载图片之优化篇
在APP应用中,listview的异步加载图片方式能够带来很好的用户体验,同时也是考量程序性能的一个重要指标.关于listview的异步加载,网上其实很多示例了,中心思想都差不多,不过很多版本或是有b ...
随机推荐
- python:爬虫入门
直接上代码吧: 一.爬取某外卖平台的指定商家菜品信息 from urllib import request import json import random url = "https:// ...
- oracle中类似indexof用法_instr函数
oracle中类似indexof用法_instr函数 [sql] 在oracle中没有indexof()函数 但是提供了一个 instr() 方法 具体用法: select instr('保定市南市区 ...
- TXB0108 TXS0108E 8-Bit Bidirectional Voltage-Level Translator for Open-Drain and Push-Pull Applications
TXS(开漏优化设计),如I2C TXB(上拉优化设计),如SPI TXS0108 has integrated pull-up resistors to save board space and c ...
- Java获取系统日期时间
方法一:利用Calendar类来获取当前日期和时间,代码如下: /** * 获取系统时间 * @return */ public String getDate(){ Calendar calendar ...
- MUI DtPicker 显示自定义日期
MUI地址:http://dev.dcloud.net.cn/mui/ 首先引入相关JS CSS脚本. HTML代码: <input class="dt flat" styl ...
- Ubuntu16.04下安装和配置Redis
一.前提条件 需要连接互联网,然后执行sudo apt-get update更新软件包 二.执行安装命令 sudo apt-get install redis-server 执行后如下图所示,我们输 ...
- 【转】JavaScript 的装载和执行
承接前面一篇文章<浏览器的渲染原理简介> ,本文来说下JavaScript的装载和执行. 通常来说,浏览器对于 JavaScript 的运行有两大特性: 1) 载入后马上执行 2) 执行时 ...
- 【Mac使用系列】常用软件及快捷键
Mac下配置ss: 下载地址:https://github.com/shadowsocks/shadowsocks-iOS/releases 旧版本:https://blog.csdn.net/vqh ...
- python eric6 IDE
之前开发一直使用sublime text + anaconda, 无意中发现了eric, Python主流IDE对比:Eric VS. PyCharm 使用IDE绝对是能提高开发效率的... http ...
- CentOS 6下 Oracle11gR2 设置开机自启动
[1] 更改/etc/oratab # This file is used by ORACLE utilities. It is created by root.sh # and updated by ...