Android ListView性能優化,異步加載圖片
來自: http://blog.csdn.net//lyhhj/article/details/48184383
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的每一項內容
<span style="font-size:14px;"><span style="font-size:14px;"><?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="match_parent" android:paddingBottom="@dimen/middler_space" android:background="#fff" android:id="@+id/llImage" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/image" android:layout_width="40dp" android:layout_height="40dp" android:background="#cccccc" android:layout_marginLeft="15dp" android:adjustViewBounds="true" android:scaleType="fitXY" android:focusable="false" android:layout_marginTop="@dimen/middler_space" /> <ImageView android:layout_marginTop="@dimen/middler_space" android:id="@+id/iv_filelist_vedio" android:src="@drawable/luxiangji" android:layout_gravity="left" android:visibility="gone" android:layout_marginLeft="15dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout> <LinearLayout android:layout_marginTop="@dimen/middler_space" android:layout_weight="1" android:orientation="vertical" android:layout_marginRight="10dp" android:layout_width="0dp" android:layout_height="wrap_content"> <TextView android:id="@+id/txtText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="title" android:textSize="15dp" android:singleLine="true" android:textColor="#000" android:layout_marginLeft="10dp" /> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="content" android:textSize="11dp" android:layout_marginLeft="10dp" android:layout_marginTop="7dp" android:textColor="@color/deep_gray"/> </LinearLayout> </LinearLayout> </LinearLayout></span></span>
很簡單就是一個titile,一個content,一張圖片
2.然后我們自定義Adapter
<span style="font-size:14px;"><span style="font-size:14px;">package com.yzx.youneed.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.LinearLayout; import android.widget.TextView; import com.nostra13.universalimageloader.core.ImageLoader; import com.yzx.youneed.R; import com.yzx.youneed.model.AppItem_file; import java.util.List; /** * Created by Hankkin on 2015/1/30. * imagelist類型適配器 */ public class AppImageListAdapter extends BaseAdapter { private Context context; private List<AppItem_file> data; private LayoutInflater inflater; public AppImageListAdapter(Context context,List<AppItem_file> data){ this.data = data; this.context = context; inflater = LayoutInflater.from(context); } @Override public int getCount() { return data.size(); } /** * 修改listview首項 * by Hankkin at:2015-2-15 * @param i * @return */ @Override public AppItem_file getItem(int i) { if (i<0){ return null; } return data.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { ViewHolder holder = null; if (view == null){ holder= new ViewHolder(); view = inflater.inflate(R.layout.listview_imagelist,null); holder.txtTitle = (TextView) view.findViewById(R.id.txtText); holder.image = (ImageView) view.findViewById(R.id.image); holder.txtContent = (TextView) view.findViewById(R.id.txtSC); view.setTag(holder); }else { holder = (ViewHolder) view.getTag(); holder.clean(); } AppItem_file af = data.get(i); if (i % 2 == 1) { view.setBackgroundResource(R.drawable.list_gray_item1); } else { view.setBackgroundResource(R.drawable.list_gray_item2); } holder.txtTitle.setText(af.getTitle()); holder.txtContent.setText(af.getCreate_time()); ImageLoader.getInstance().displayImage(af.getThumbnail(),holder.image); return view; } public final class ViewHolder{ public TextView txtTitle,txtContent; public ImageView image; void clean(){ txtTitle.setText(null); txtContent.setText(null); image.setImageBitmap(null); } } }</span></span>我們可以看見我們自己定義的ViewHolder,里面存放著item里面的三個屬性,在getView的時候如果view為空,我們新建一個view,如果不為空,我們的holder=view.getTag();大家可能注意到還有一個clean()方法,這個方法是為了防止我們每一個item的數據會重復,然后我們每加載一個item之后都把上一個的item的數據源置空。
加載圖片我們用的是
服務器獲取數據之后添加到List中更新我們的適配器就ok了,這時候我們的ListView就已經有數據了。
只需要簡單的這么一句話就搞定,是不是很方便?
這里面有加載圖片失敗的設置,默認圖片的設置,延遲加載設置,以及緩存陌路設置等等,這里就不詳細介紹了,一般這個方法基本的配置都有了,大家可以直接拷到你的項目中直接用,可以在application里面初始化Imageloader。如果大家想要詳細的了解Imageloader框架的話可以看看
<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,所以訪問服務器我就用它了,只是給大家舉個例子
<span style="font-size:14px;"><span style="font-size:14px;">public void asyncQF(boolean url1) { RequestParams params = new RequestParams(); params.addBodyParameter("flag",file_group.getFlag()); HttpUtils http = new HttpUtils(); http.send(HttpRequest.HttpMethod.POST, "", new RequestCallBack<String>() { @Override public void onSuccess(ResponseInfo<String> responseInfo) { //ToDo: //添加數據源,更新適配器 } @Override public void onFailure(HttpException error, String msg) { //ToDo: //更新UI } }); }</span></span>
服務器獲取數據之后添加到List中更新我們的適配器就ok了,這時候我們的ListView就已經有數據了。
最后我們還可以設置ListView滑動時不加載圖片
4.設置滑動不加載圖片
ImageLoader已經給我們封裝好了方法,我們只需要設置一下ListView滑動監聽就可以了,看一下代碼:
<span style="font-size:14px;"><span style="font-size:18px;"> lv_appImageList.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(),false,true));</span> </span>
只需要簡單的這么一句話就搞定,是不是很方便?
四、ImageLoader配置
<span style="font-size:14px;"><span style="font-size:14px;">public static void initImageLoader(Context context) { personOptions = new DisplayImageOptions.Builder() .showImageOnFail(R.drawable.usericon) .showImageForEmptyUri(R.drawable.usericon) .resetViewBeforeLoading(false) // default .delayBeforeLoading(0) .cacheInMemory(true) // default .cacheOnDisk(true) // default .considerExifParams(true) // default .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default .bitmapConfig(Bitmap.Config.ARGB_8888) // default .displayer(new SimpleBitmapDisplayer()) // default .handler(new Handler()) // default .build(); DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.download) // .showImageOnFail(R.drawable.img_fail) .resetViewBeforeLoading(false) // default .delayBeforeLoading(0) .cacheInMemory(true) // default .cacheOnDisk(true) // default .considerExifParams(true) // default .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // default .bitmapConfig(Bitmap.Config.ARGB_8888) // default .displayer(new SimpleBitmapDisplayer()) // default .handler(new Handler()) // default .build(); // This configuration tuning is custom. You can tune every option, you may tune some of them, // or you can create default configuration by // ImageLoaderConfiguration.createDefault(this); // method. // File cacheDir = StorageUtils.getCacheDirectory(context); File picPath=new File(Environment.getExternalStorageDirectory().getPath()+File.separator+"yourneed"+File.separator+"files"); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .memoryCacheExtraOptions(480, 800) // default = device screen dimensions .diskCacheExtraOptions(480, 800, null) .threadPoolSize(3) // default .threadPriority(Thread.NORM_PRIORITY - 1) // default .tasksProcessingOrder(QueueProcessingType.FIFO) // default .denyCacheImageMultipleSizesInMemory() .memoryCache(new LruMemoryCache(2 * 1024 * 1024)) .memoryCacheSize(2 * 1024 * 1024) .memoryCacheSizePercentage(13) // default .diskCache(new UnlimitedDiscCache(picPath)) // default .diskCacheSize(50 * 1024 * 1024) .diskCacheFileCount(1000) .diskCacheFileNameGenerator(new HashCodeFileNameGenerator()) // default .imageDownloader(new BaseImageDownloader(context)) // default .imageDecoder(new BaseImageDecoder(true)) // default .defaultDisplayImageOptions(options) // default .writeDebugLogs() .build(); // Initialize ImageLoader with configuration. ImageLoader.getInstance().init(config); }</span></span>
這里面有加載圖片失敗的設置,默認圖片的設置,延遲加載設置,以及緩存陌路設置等等,這里就不詳細介紹了,一般這個方法基本的配置都有了,大家可以直接拷到你的項目中直接用,可以在application里面初始化Imageloader。如果大家想要詳細的了解Imageloader框架的話可以看看
這兩篇博客,還是比較不錯的。
至于圖片就不給大家貼了,只要按照上面的方法做,你的ListView相信不會卡頓的。
本文由用戶 NoeGooden 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!