在我蒐集了相關的資料後,大致上有了初步debug的方向,
讓 adapter在 getview時少做點事情
根據android developer文件描述
Your code might call
findViewById()
frequently during the scrolling of ListView
, which can slow down performance. Even when the Adapter
returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById()
is to use the "view holder" design pattern.意思就是使用viewholder pattern來減少 findviewById的動作,
範例如下
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder ; if(convertView==null){ LayoutInflater inflater = LayoutInflater.from(getContext()); convertView = inflater.inflate(R.layout.listviewLayout, null,false); holder = new ViewHolder(); holder.title = (TextView)convertView.findViewById(R.id.title); convertView.setTag(holder); }else{ holder = (ViewHolder)convertView.getTag(); } holder.title.setText("ha"); return convertView; } static class ViewHolder{ TextView title; }
除了使用viewholder pattern之外,當然也要極力避免在getview時做init的動作,
所有的事情最好在第一次 if(convertView == null) 時就將事情做掉,
例如background的設置,文字顏色設置,view的size,時間的計算...etc,總之能不在getview裡做的就別在裡面做
避免GC頻繁的發生
當我們在getView create Object 並且將他們destroy ,這會造成GC頻繁的被觸發,我們只需要看debug log,就可以知道GC是否在getview時不斷的觸發。
Load Image
根據android developer的建議是使用async task的方式去讀取圖片,
// Using an AsyncTask to load the slow images in a background thread new AsyncTask<ViewHolder, Void, Bitmap>() { private ViewHolder v; @Override protected Bitmap doInBackground(ViewHolder... params) { v = params[0]; return mFakeImageLoader.getImage(); } @Override protected void onPostExecute(Bitmap result) { super.onPostExecute(result); if (v.position == position) { // If this item hasn't been recycled already, hide the // progress and set and show the image v.progress.setVisibility(View.GONE); v.icon.setVisibility(View.VISIBLE); v.icon.setImageBitmap(result); } } }.execute(holder);其實網路上有一些 solution,Picasso , Universal Image Loader,使用他們可以快速解決讀取圖片的問題。
使用scrollingCache 和 animateCache
使用scrollingCache其實就是個DrawingCache,使用他可以避免在每個frame重畫view,進而達到速度的提升,當然他的缺點就是會花費memory。
animationCache 就是layout animation時是否需要使用drawingCache,使用animationCache 需要花費較多的memory,但是可以換來較好的performance。
範例如下
<ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:animationCache="true" android:scrollingCache="true" />
盡量將layout攤平
看一下下面的範例
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="a" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="b" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="c" /> </LinearLayout> </LinearLayout>
其實上面的layout使用relativeLayout 一層就可以搞定了,越多層layout會使getview花越多時間,基本上三層以上就會很有感覺了
如果能使用圖片,盡量使用圖片
有些時候會為了客制某些圖樣,我們必須使用如下的方式去繪製圖片
<LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/a" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/b" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/c" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/d" /> </LinearLayout>
example of a.xml
<item> <layer-list> <item android:bottom="4dp" android:bottom="4dp"> ... </item> <item android:left="4dp" android:top="4dp"> ... </item> </layer-list> </item>
自己畫的好處是,即使螢幕變寬變長,layout不至於被影響,缺點是當所有的layout都用畫的,其實getview會花費較多的時間,我會發現這個的原因,是由於我客製的layout不過是一個linearlayout裡面包含分隔線還有一些文字,但是只要這個layout出現,畫面就會變得很頓,在經過了多方嘗試之後,我決定使用圖片,所有的問題就迎刃而解了。
最後附上 reference
在android 中要讓 listview平順的滑動真的需要花很多時間去tune啊...
沒有留言:
張貼留言