一.item 的layout中盡量避免使用wrap_content ,可以使用固定的dp/dip,或者fill_parent/match_parent ; View在Draw的時候分成兩個階段:measure和layout,在measure階段時主要就是為了計算兩個參數:height和width。而且要注意的是,這是個遞歸的過程,從頂向下,DecorView開始依次調用自己子元素的measure。計算完成這兩個參數後就開始layout,最後再是draw的調用。 wrap_content 要計算自己的大小,fill_parent填充父view給的大小,減少了計算。
對于ListView,當然每一個Item都會被調用measure方法,而在這個過程中getView和getCount會被調用,根據操作,可能會有很多次調用。
二.Doesn't show fading edges.
三.注意adapter中getview裡面的緩存處理。利用convertview回收視圖,效率提高200%。利用viewholder模式,效率在提高50%。
1. ListView需要設定adapter,它的item是通過adapter的方法getView(int position, View convertView, ViewGroup parent)獲得的。
2. ListView中隻有第一屏的item需要建立,它的引用會被存在RecycleBin對象内,在拖動時後面的item實際上是重從了之前建立的item。
3. 根據上述,ListView在需要顯示item時,最開始第一屏時,getView(int position, View convertView, ViewGroupparent )的第二個參數為null,顯示第二屏或者復原顯示第一屏時,getView(int position, View convertView, ViewGroupparent )第二個參數是一個原來緩存的item,我們隻需要在getView中把它内部資料更新即可。
4. 如果item結構比較複雜,在更新一個已有的item内部資料的時候,查找item内部每一個元素也需要占用不少資源,是以,可以把這些内部元素的引用緩存起來,直接對其指派,最有效的方法是把這些引用存到對應的item中,比較好的方法是使用setTag()方法。
據上四條,可得出:
1. 在adapter的getView(int position, View convertView, ViewGroup parent)方法中,每次都new一個新的View傳回,是性能最差的,浪費了ListView巧妙設計的一片苦心。
2. 如果item内部元素簡單,getView中如果傳進來的view不為空,直接為其指派即可。
3. 如果item内部元素複雜,可以使用Google IO 大會中讨論的方法優化(如下):
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
holder = new ViewHolder();
holder.icon1 = (ImageView) convertView.findViewById(R.id.icon1);
holder.text1 = (TextView) convertView.findViewById(R.id.text1);
convertView.setTag(holder);
}
else{
holder = (ViewHolder)convertView.getTag();
}
holder.icon1.setImageResource(R.drawable.icon);
holder.text1.setText(mData[position]);
return convertView;
}
static class ViewHolder {
TextView text1;
ImageView icon1;
}
四.簡化視圖和布局
如果一個視窗包含很多視圖,啟動太慢,繪制時間長,使用者界面反應速度很慢,解決方法:
1。使用textview的複合drawable減少層次
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello"
android:drawableLeft="@drawable/icon"/>
2。使用viewstuf延遲展開視圖
在xml檔案中定義viewstuf
<ViewStub android:id = "@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"/>
在需要展開視圖時,
findViewById(R.id.stub_import).setVisibility(View.VISIBLE);
// 或者
View importPanel = ((ViewStub)
findViewById(R.id.stub_import)).inflate();
3。使用<merge>合并中間視圖
預設情況下,布局檔案的根作為一個節點,加入到父視圖中,如果使用merge可以避免根節點
<merge xmlns:android = "http://schemas.android.com/apk/res/android">
<! -- Content -->
</merge>
4。使用ralativelayout減少層次
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<ImageView android:id="@+id/icon"
android:layout_width="48dip" android:layout_height="48dip"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/text_line1"
android:layout_alignParentTop="true"
android:layout_toRightOf="@id/icon"/>
<TextViewandroid:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/text_line2"
android:layout_toRightOf="@id/icon"
android:layout_below="@id/text_line1"/>
<Checkbox android:id="@+id/star"
android:layout_width="48dip" android:layout_height="48dip"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
5.使用自定義視圖
class CustomView extends View {
@Override
protected void onDraw(Canvascanvas) {
// 加入你的繪圖編碼
}
@Override
protected void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
// 計算視圖的尺寸
setMeasuredDimension(widthSpecSize, heightSpecSize);
}
}
6 使用自定義布局
class GridLayout extends ViewGroup {
@Override
protected void onLayout(boolean changed, int l, int t,
int r, int b) {
final int count =getChildCount();
for (int i=0; i <count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() !=GONE) {
// 計算子視圖的位置
child.layout(left, top, right, bottom);
}
}
}
}
五.更新看不見的背景是浪費時間,可設定相關控件背景為空
1。代碼設定
public void onCreate(Bundleicicle){
super.onCreate(icicle);
setContentView(R.layout.mainview);
// 删除視窗背景
getWindow().setBackgroundDrawable(null);
...
}
2。Xml設定
首先确定你的res/values/styles.xml有
<resources>
<style name="NoBackgroundTheme" parent="android:Theme">
<itemname="android:windowBackground">@null</item>
</style>
</resources>
然後編輯androidmainfest.xml
<activity android:name="MyApplication"
android:theme="@style/NoBackgroundTheme">
...
</activity>
六.控制記憶體配置設定
在性能敏感的代碼裡,避免建立java對象:
1。測量 onmeasure()
2。布局onlayout()
3。繪圖 ondraw() dispatchdraw()
4。事件處理 ontouchevent() dispatchtouchevent()
5。adapter: getview() bindview()
在調試模式下進行強行限制
int prevLimit = -1;
try {
prevLimit = Debug.setAllocationLimit(0);
// 執行不配置設定記憶體的代碼
} catch (dalvik.system.AllocationLimitErrore) {
// 如果代碼配置設定記憶體, Java 虛拟機會抛出錯誤
Log.e(LOGTAG, e);
} finally {
Debug.setAllocationLimit(prevLimit);
}
管理好對象:
1。适用軟引用:記憶體緩存的最佳選擇
2。适用弱引用:避免記憶體洩露
private final HashMap<String,SoftReference<T>> mCache;
public void put(Stringkey, T value) {
mCache.put(key, new SoftReference<T>(value));
}
public T get(String key, ValueBuilderbuilder) {
T value = null;
SoftReferece<T> reference = mCache.get(key);
if (reference != null) {
value = reference.get();
參考過幾篇博文,自己也試用過的一些方法。特此整理,亦可參考http://edu.gamfe.com/tutor/d/30509.html等有樣例測試的文章。