ListView性能优化+异步加载图片

一、绪论

相信大家在Android开发中肯定会经常用到ListView吧,那么怎么优化ListView呢?尤其是每个item里面中还有图片需要加载,数据源比较多,如果处理不好的话,在滑动ListView的过程中肯定会遇到卡顿的现象,做了这么久的开发,自己多少也摸索到了一些规律,接下来就给大家详细的介绍一下ListView的性能优化。

二、思路:

1.利用ViewHolder

我们自己定义一个ViewHolder,存放我们item中的组件,减少不必要的findViewById(),把我们的控件引用存在里面,利用view.setTag()存放在view里面,下次就可以直接取了。说一下setTag()是干什么用的吧,就是给View一个标签,下次getView()的时候我们可以根据标签获取这个View,如果标签存在了,就不需要再创建了,也就不再需要重新初始化那些组件了。

2.异步加载图片

我们在ListView中异步加载图片,可以使用一些第三方API来加载图片,比较好用的是ImageLoader,Xutils里面的BitmapUtils也可以。

3.设置LitView滑动时禁止加载图片

如果我们在滑动ListView的时候也要加载图片,那么滑动时肯定会卡顿

三、详解:

1.定义ListView

我们先看一下布局,item的每一项内容
[java]  view plain copy print ?
  1. <span style="font-size:14px;"><span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.               android:orientation="horizontal"  
  4.               android:layout_width="match_parent"  
  5.               android:layout_height="match_parent"  
  6.               android:paddingBottom="@dimen/middler_space"  
  7.               android:background="#fff"  
  8.               android:id="@+id/llImage"  
  9.         >  
  10.         <RelativeLayout  
  11.                 android:layout_width="wrap_content"  
  12.                 android:layout_height="wrap_content">  
  13.   
  14.                 <ImageView  
  15.                         android:id="@+id/image"  
  16.                         android:layout_width="40dp"  
  17.                         android:layout_height="40dp"  
  18.                         android:background="#cccccc"  
  19.                         android:layout_marginLeft="15dp"  
  20.                         android:adjustViewBounds="true"  
  21.                         android:scaleType="fitXY"  
  22.                         android:focusable="false"  
  23.                         android:layout_marginTop="@dimen/middler_space"  
  24.                         />  
  25.                 <ImageView  
  26.                         android:layout_marginTop="@dimen/middler_space"  
  27.                         android:id="@+id/iv_filelist_vedio"  
  28.                         android:src="@drawable/luxiangji"  
  29.                         android:layout_gravity="left"  
  30.                         android:visibility="gone"  
  31.                         android:layout_marginLeft="15dp"  
  32.                         android:layout_width="wrap_content"  
  33.                         android:layout_height="wrap_content"/>  
  34.         </RelativeLayout>  
  35.   
  36.         <LinearLayout  
  37.                 android:layout_marginTop="@dimen/middler_space"  
  38.                 android:layout_weight="1"  
  39.                 android:orientation="vertical"  
  40.                 android:layout_marginRight="10dp"  
  41.                 android:layout_width="0dp"  
  42.                 android:layout_height="wrap_content">  
  43.             <TextView  
  44.                     android:id="@+id/txtText"  
  45.                     android:layout_width="wrap_content"  
  46.                     android:layout_height="wrap_content"  
  47.                     android:text="title"  
  48.                     android:textSize="15dp"  
  49.                     android:singleLine="true"  
  50.                     android:textColor="#000"  
  51.                     android:layout_marginLeft="10dp"  
  52.                     />  
  53.             <LinearLayout  
  54.                     android:orientation="horizontal"  
  55.                     android:layout_width="wrap_content"  
  56.                     android:layout_height="wrap_content">  
  57.                 <TextView  
  58.                         android:layout_width="wrap_content"  
  59.                         android:layout_height="wrap_content"  
  60.                         android:text="content"  
  61.                         android:textSize="11dp"  
  62.                         android:layout_marginLeft="10dp"  
  63.                         android:layout_marginTop="7dp"  
  64.                         android:textColor="@color/deep_gray"/>  
  65.                   
  66.             </LinearLayout>  
  67.   
  68.         </LinearLayout>  
  69.   
  70. </LinearLayout></span></span>  

很简单就是一个titile,一个content,一张图片

2.然后我们自定义Adapter

[java]  view plain copy print ?
  1. <span style="font-size:14px;"><span style="font-size:14px;">package com.yzx.youneed.adapter;  
  2.   
  3. import android.content.Context;  
  4. import android.view.LayoutInflater;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7. import android.widget.BaseAdapter;  
  8. import android.widget.ImageView;  
  9. import android.widget.LinearLayout;  
  10. import android.widget.TextView;  
  11. import com.nostra13.universalimageloader.core.ImageLoader;  
  12. import com.yzx.youneed.R;  
  13. import com.yzx.youneed.model.AppItem_file;  
  14.   
  15. import java.util.List;  
  16.   
  17. /** 
  18.  * Created by Hankkin on 2015/1/30. 
  19.  * imagelist类型适配器 
  20.  */  
  21. public class AppImageListAdapter extends BaseAdapter {  
  22.     private Context context;  
  23.     private List<AppItem_file> data;  
  24.     private LayoutInflater inflater;  
  25.     public AppImageListAdapter(Context context,List<AppItem_file> data){  
  26.         this.data = data;  
  27.         this.context = context;  
  28.         inflater = LayoutInflater.from(context);  
  29.     }  
  30.     @Override  
  31.     public int getCount() {  
  32.         return data.size();  
  33.     }  
  34.     /** 
  35.      * 修改listview首项 
  36.      * by Hankkin at:2015-2-15 
  37.      * @param i 
  38.      * @return 
  39.      */  
  40.     @Override  
  41.     public AppItem_file getItem(int i) {  
  42.         if (i<0){  
  43.             return null;  
  44.         }  
  45.         return data.get(i);  
  46.     }  
  47.   
  48.     @Override  
  49.     public long getItemId(int i) {  
  50.         return i;  
  51.     }  
  52.   
  53.       
  54.     @Override  
  55.     public View getView(int i, View view, ViewGroup viewGroup) {  
  56.         ViewHolder holder = null;  
  57.         if (view == null){  
  58.             holder= new ViewHolder();  
  59.             view = inflater.inflate(R.layout.listview_imagelist,null);  
  60.             holder.txtTitle = (TextView) view.findViewById(R.id.txtText);  
  61.             holder.image = (ImageView) view.findViewById(R.id.image);  
  62.             holder.txtContent = (TextView) view.findViewById(R.id.txtSC);  
  63.             view.setTag(holder);  
  64.         }else {  
  65.             holder = (ViewHolder) view.getTag();  
  66.             holder.clean();  
  67.         }  
  68.   
  69.         AppItem_file af = data.get(i);  
  70.         if (i % 2 == 1) {  
  71.             view.setBackgroundResource(R.drawable.list_gray_item1);  
  72.         } else {  
  73.             view.setBackgroundResource(R.drawable.list_gray_item2);  
  74.         }  
  75.         holder.txtTitle.setText(af.getTitle());  
  76.         holder.txtContent.setText(af.getCreate_time());  
  77.         ImageLoader.getInstance().displayImage(af.getThumbnail(),holder.image);  
  78.         return view;  
  79.     }  
  80.   
  81.     public final class ViewHolder{  
  82.         public TextView txtTitle,txtContent;  
  83.         public ImageView image;  
  84.         void clean(){  
  85.             txtTitle.setText(null);  
  86.             txtContent.setText(null);  
  87.             image.setImageBitmap(null);  
  88.         }  
  89.     }  
  90.   
  91. }</span></span>  
我们可以看见我们自己定义的ViewHolder,里面存放着item里面的三个属性,在getView的时候如果view为空,我们新建一个view,如果不为空,我们的holder=view.getTag();大家可能注意到还有一个clean()方法,这个方法是为了防止我们每一个item的数据会重复,然后我们每加载一个item之后都把上一个的item的数据源置空。
加载图片我们用的是
  
  
  1. <span style="font-size:14px;"><span style="font-size:18px;">ImageLoader.getInstance().displayImage(af.getThumbnail(),holder.image);</span></span>  
这句话也就是ImageLoader的异步加载图片,只需要传进去两个参数,第一个是图片url,第二个是ImageView控件,ImageLoader会自动给我们缓存图片的,如果之前加载过了是不会再次下载图片,直接加载本地缓存好的图片。至于ImageLoader的一些配置信息,包括默认图片,缓存地址等会在下面介绍。

3.接下来我们看一下怎么在我们的Activity中访问服务器获取信息

因为项目里面用的是Xutils的HttpUtils,所以访问服务器我就用它了,只是给大家举个例子
[java]  view plain copy print ?
  1. <span style="font-size:14px;"><span style="font-size:14px;">public void asyncQF(boolean url1) {  
  2.         RequestParams params = new RequestParams();  
  3.         params.addBodyParameter("flag",file_group.getFlag());  
  4.         HttpUtils http = new HttpUtils();  
  5.         http.send(HttpRequest.HttpMethod.POST, ""new RequestCallBack<String>() {  
  6.             @Override  
  7.             public void onSuccess(ResponseInfo<String> responseInfo) {  
  8.                 //ToDo:  
  9.                 //添加数据源,更新适配器  
  10.             }  
  11.   
  12.             @Override  
  13.             public void onFailure(HttpException error, String msg) {  
  14.                 //ToDo:  
  15.                 //更新UI  
  16.             }  
  17.         });  
  18.     }</span></span>  

服务器获取数据之后添加到List中更新我们的适配器就ok了,这时候我们的ListView就已经有数据了。
最后我们还可以设置ListView滑动时不加载图片

4.设置滑动不加载图片

ImageLoader已经给我们封装好了方法,我们只需要设置一下ListView滑动监听就可以了,看一下代码:
[java]  view plain copy print ?
  1. <span style="font-size:14px;"><span style="font-size:18px;">        lv_appImageList.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(),false,true));</span>  
  2. </span>  

只需要简单的这么一句话就搞定,是不是很方便?

四、ImageLoader配置

[java]  view plain copy print ?
  1. <span style="font-size:14px;"><span style="font-size:14px;">public static void initImageLoader(Context context) {  
  2.         personOptions = new DisplayImageOptions.Builder()  
  3.                 .showImageOnFail(R.drawable.usericon)  
  4.                 .showImageForEmptyUri(R.drawable.usericon)  
  5.                 .resetViewBeforeLoading(false)  // default  
  6.                 .delayBeforeLoading(0)  
  7.                 .cacheInMemory(true// default  
  8.                 .cacheOnDisk(true// default  
  9.                 .considerExifParams(true// default  
  10.                 .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default  
  11.                 .bitmapConfig(Bitmap.Config.ARGB_8888) // default  
  12.                 .displayer(new SimpleBitmapDisplayer()) // default  
  13.                 .handler(new Handler()) // default  
  14.                 .build();  
  15.   
  16.         DisplayImageOptions options = new DisplayImageOptions.Builder()  
  17.                 .showImageOnLoading(R.drawable.download)  
  18. //                .showImageOnFail(R.drawable.img_fail)  
  19.                 .resetViewBeforeLoading(false)  // default  
  20.                 .delayBeforeLoading(0)  
  21.                 .cacheInMemory(true// default  
  22.                 .cacheOnDisk(true// default  
  23.                 .considerExifParams(true// default  
  24.                 .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default  
  25.                 .bitmapConfig(Bitmap.Config.ARGB_8888) // default  
  26.                 .displayer(new SimpleBitmapDisplayer()) // default  
  27.                 .handler(new Handler()) // default  
  28.                 .build();  
  29.   
  30.         // This configuration tuning is custom. You can tune every option, you may tune some of them,  
  31.         // or you can create default configuration by  
  32.         // ImageLoaderConfiguration.createDefault(this);  
  33.         // method.  
  34. //        File cacheDir = StorageUtils.getCacheDirectory(context);  
  35.         File picPath=new File(Environment.getExternalStorageDirectory().getPath()+File.separator+"yourneed"+File.separator+"files");  
  36.         ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)  
  37.                 .memoryCacheExtraOptions(480800// default = device screen dimensions  
  38.                 .diskCacheExtraOptions(480800null)  
  39.                 .threadPoolSize(3// default  
  40.                 .threadPriority(Thread.NORM_PRIORITY - 1// default  
  41.                 .tasksProcessingOrder(QueueProcessingType.FIFO) // default  
  42.                 .denyCacheImageMultipleSizesInMemory()  
  43.                 .memoryCache(new LruMemoryCache(2 * 1024 * 1024))  
  44.                 .memoryCacheSize(2 * 1024 * 1024)  
  45.                 .memoryCacheSizePercentage(13// default  
  46.                 .diskCache(new UnlimitedDiscCache(picPath)) // default  
  47.                 .diskCacheSize(50 * 1024 * 1024)  
  48.                 .diskCacheFileCount(1000)  
  49.                 .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default  
  50.                 .imageDownloader(new BaseImageDownloader(context)) // default  
  51.                 .imageDecoder(new BaseImageDecoder(true)) // default  
  52.                 .defaultDisplayImageOptions(options) // default  
  53.                 .writeDebugLogs()  
  54.                 .build();  
  55.         // Initialize ImageLoader with configuration.  
  56.         ImageLoader.getInstance().init(config);  
  57.     }</span></span>  

这里面有加载图片失败的设置,默认图片的设置,延迟加载设置,以及缓存陌路设置等等,这里就不详细介绍了,一般这个方法基本的配置都有了,大家可以直接拷到你的项目中直接用,可以在application里面初始化Imageloader。如果大家想要详细的了解Imageloader框架的话可以看看
这两篇博客,还是比较不错的。
至于图片就不给大家贴了,只要按照上面的方法做,你的ListView相信不会卡顿的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值