編輯:關於Android編程
在Android App的開發中, ListView和GridView等控件是使用非常頻繁的控件。 這兩個控件的特點是使用數據適配器來顯示數據, 並且在數據項較多的時候, 可以重用用於顯示數據的條目(這裡的條目指的是ListView或GridView中用於顯示每一個數據項的子View)。本文的重點並不是講解ListView和GridView的內部實現或使用方法,但是後文講解的自定義Adapter是被ListView和GridView所調用的,所以在這裡簡單提及ListView和GridView。ListView,GridView和Adapter的關系如下圖所示:
從上述代碼可以看出, getView方法中處理的邏輯有兩個: 1 判斷是否可以重用View, 如果不能重用, 就創建新的條目View, 找到條目View中的各個子View, 被存放在一個ViewHolder獨享中。如果可以重用View, 就重用這個view, 並且從和這個View相關的ViewHolder對象中找到已經緩存的子View。 2 將具體的數據和事件綁定到各個子View上。 1 判斷是否可以重用View, 如果不能重用, 就創建新的條目View, 找到條目View中的各個子View, 被存放在一個ViewHolder獨享中。如果可以重用View, 就重用這個view, 並且從和這個View相關的ViewHolder對象中找到已經緩存的子View。 2 將具體的數據和事件綁定到各個子View上。
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPGgxPsrKxeTG97XE0ruw48q508O3vcq9PC9oMT4KPGJyPgoK08nT2kdyaWRWaWV3tcTKudPDt73KvbrNTGlzdFZpZXe63M/gJiMyMDI4NDujrCDOqsHL0PDK9rXEvPK94KOsIM/CzsTWu9LUTGlzdFZpZXfOqsD9vbK94qGj1Nq/qrei1tCjrExpc3RWaWV3us1BZGFwdGVytcTKudPDt73KvdK7sOPH6b/2z8LKx9Xi0fm1xKO6Cjxicj4KCjEgvMyz0FNES9bQtcRCYXNlQWRhcHRlcqOsIMq1z9a6zdK1zvHP4LnYtcTX1Lao0uVBZGFwdGVyCjxicj4KCjIgtLS9qNK7uPZBZGFwdGVytcTKtcD9o6wgtffTw0xpc3RWaWV3tcRzZXRBZGFwdGVyt723qKOsIL2r1eK49kFkYXB0ZXK21M/zo6wgyejWw7W9TGlzdFZpZXe21M/ztcTE2rK/oaMKPGJyPgoK1NrV4sDv1vfSqr2yyvbKtc/W19S2qNLlQWRhcHRlcrXEuf2zzKGjINTavMyz0EJhc2VBZGFwdGVyuvOjrCDSqsq1z9ZCYXNlQWRhcHRlctbQtqjS5bXEs+nP87e9t6hnZXRWaWV3oaNnZXRWaWV3t723qMrH08lMaXN0Vmlld7bUz/O199PDtcShoyC4xcCo0rvPwqOsIL7NysdMaXN0Vmlld7bUz/PU2tDo0qrSu7j20MK1xMz1xL9WaWV3tcTKsbryo6wgu+G199PD1eK49mdldFZpZXe3vbeoo6zE47HY0OvKtc/W1eK49re9t6ijrLe1u9jSu7j217yxuLrDtcRWaWV3oaO1q8rHo6xMaXN0Vmlld77f09DW2NPDzPXEv1ZpZXe1xLmmxNyhowog0rK+zcrHsrvKx8O/tM7Q6NKq0ru49sz1xL9WaWV3try00823tLS9qKGjy/nS1GdldFZpZXe3vbeo09DSu7j2ss7K/WNvbnZlcnRWaWV3o6wg1eK49tKyysfTyUxpc3RWaWV3tKu1vUFkYXB0ZXLW0LXEoaMgtbFMaXN0Vmlld9bQtObU2sTcubvW2NPDtcRWaWV3yrG+zb2r1eK49lZpZXe0q7W9Z2V0Vmlld7e9t6jW0KGjIGdldFZpZXe3vbeotcTKtc/W1d/SqsXQts9jb252ZXJ0Vmlld8rHt/HOqr/Vo6wgyOe5+7K7zqq/1aOsIL7N1tjTw9XiuPZWaWV3oaMKPGJyPgoK19S2qNLlQWRhcHRlctbQtcRnZXRWaWV3yrXP1re9yr3Su7DjyOfPwqO6o6jV4sDvzqrBy73ayqHKsbzko6zWsb3TyrnTw8/uxL/W0LXEtPrC66OsILbB1d/Wu9DoudjXomdldFZpZXcgtcTKtc/W0M7KvaOsILK708O52NDE0rXO8c/gudi1xLHkwb/D+7PGo6kKPGJyPgoKPHByZSBjbGFzcz0="brush:java;"> private static class ScheduleAdapter extends BaseAdapter{
private List
實現自動重用View的Adapter
從上面的代碼經常被使用到, 每次都要在getView方法中寫這些重用View的邏輯, 並且還要每次都寫一個業務相關的ViewHolder類,真的是非常非常惡心。那麼有沒有辦法封裝一下這些惡心的邏輯,而不用每次都從頭寫起呢? 本文提供了一種實現方法。
首先給出完整的實現代碼, 然後對代碼中的關鍵點進行分析。
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
/**
* 一個具有自動重用View功能的適配器實現
*
* @author zhangjg
* @date Feb 20, 2014 10:57:42 AM
*/
public abstract class AutoReuseViewAdapter extends BaseAdapter {
//Item布局資源
private int itemLayoutRes;
//Item中要操作的各個子View的Id
private int[] childViewIds;
//布局填充器
private LayoutInflater inflator;
public AutoReuseViewAdapter(Context context, int itemLayoutRes, int ... childViewIds) {
inflator = LayoutInflater.from(context);
this.itemLayoutRes = itemLayoutRes;
this.childViewIds = childViewIds;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = null;
ViewHolder holder;
if(convertView != null){
v = convertView;
holder = (ViewHolder) v.getTag();
}else{
v = inflator.inflate(itemLayoutRes, null);
holder = new ViewHolder();
for(int childId : childViewIds ){
holder.cacheView(v.findViewById(childId));
}
v.setTag(holder);
}
boundDataAndEventToViews(position, v, holder.getCachedViews());
return v;
}
/**
* 抽象方法, 被子類覆蓋, 將業務相關的數據和事件綁定到特定的子View上
*/
protected abstract void boundDataAndEventToViews(int position,
View itemView, ArrayList
首先解釋一下這個抽象類的成員變量。 itemLayoutRes是條目View的布局資源, childViewIds是一個int型的數組, 用於存放條目View中要處理的各個子View的id 。 這兩個成員變量是通過構造方法注入的, 代碼如下:
private int itemLayoutRes;
//Item中要操作的各個子View的Id
private int[] childViewIds;
//布局填充器
private LayoutInflater inflator;
public AutoReuseViewAdapter(Context context, int itemLayoutRes, int ... childViewIds) {
inflator = LayoutInflater.from(context);
this.itemLayoutRes = itemLayoutRes;
this.childViewIds = childViewIds;
}
在構造方法中, 還要根據context創建一個LayoutInflater對象, 用於從XML布局中加載條目View。
然後說一下getView方法的實現。 這個類中, 將getView中的邏輯分到兩個方法中去處理。首先重用View的邏輯是業務無關的, 在getView 中實現, 將數據和事件綁定到各個子View上是業務相關的, 交給boundDataAndEventToViews方法處理, 這是個抽象方法, 必須由子類覆蓋並實現, 因為業務相關的東西也只有具體子類才知道。
現在再從整體上審視一下這個Adapter的實現。 由於getView是由ListView調用的, 至於如何調用, 何時調用我們無法干預,但是不管怎麼寫代碼, getView方法必須完成屬於他的所有任務。 這裡再重復一下getView 的職責:
在我們實現的這個AutoReuseViewAdapter中, getView方法同樣完成了兩個職責。 也就是說原有的處理流程還是由getView方法定義, 只是將部分邏輯(綁定數據和事件到子View)交給具體子類去實現, 這是標准的模板方法設計模式。
使用自動重用View功能的Adaper
在上面的步驟中, AutoReuseViewAdapter已經實現好了。 現在就看看如何根據這個AutoReuseViewAdapter實現自己業務相關的Adapter。基於AutoReuseViewAdapter實現自己的Adapter, 只需要做以下工作:
1 自定義自己的Adapter, 繼承AutoReuseViewAdapter;
2 在子類的構造方法中調用父類AutoReuseViewAdapter的構造方法, 將條目布局的資源索引和條目View中各個子View 的Id傳到父類構造器中;
3 覆蓋並實現父類中的抽象方法, 在boundDataAndEventToViews方法中對子View進行數據和事件綁定。
在上面“適配器的一般使用方式“一節中, 給出了適配器的一般實現。 現在我們基於AutoReuseViewAdapter重新實現它, 看看是不是簡單了很多。下面是重新實現的版本:
private static class ScheduleAdapter extends /*BaseAdapter*/AutoReuseViewAdapter{
private List
看, 是不是變得簡單多了。 我們現在只需要關心業務相關的邏輯了, 不用再關心業務無關的邏輯(重用View的邏輯)。所以,
如果在項目中有一些業務無關的代碼總是重復的寫, 那麼有很大可能有優化的余地, 這時我們就要發揚程序員的”懶惰“的優良傳統,將重復的邏輯抽取出來。
最後有兩點需要強調:
1 因為父類中的getView方法定義了完整的邏輯流程, 所以子類絕對不要覆蓋getView方法, 只要實現boundDataAndEventToViews方法就夠了。
2 boundDataAndEventToViews方法中, 需要綁定數據和事件的子View是由一個集合ArrayList
android給我們提供了一個spinner控件,這個控件主要就是一個列表,那麼我們就來說說這個控件吧,這個控件在以前的也看見過,但今天還是從新介紹一遍吧。Spinner
再做一個項目的時候,要求標題欄的標題再中間,樣式,字體大小都要自定義。左邊一個返回按鈕,一個關閉按鈕,右邊定義一個提交按鈕,有時候顯示有時候隱藏。因為原生的title標題
項目涉及藍牙通信,所以就簡單的學了學,下面是自己參考了一些資料後的總結,希望對大家有幫助。 以下是開發中的幾個關鍵步驟:1、首先開啟藍牙 2、搜索可用
主要實現辦法:動態加載各級下拉值的適配器在監聽本級下拉框,當本級下拉框的選中值改變時,隨之修改下級的適配器的綁定值 &