ソース解析-ListViewコンポーネントaddHeaderView()メソッドのソース解析
10310 ワード
ぶんせきりょく
最近、自分のプロジェクトを書いて、RecyclerViewというコントロールを使って、私が以前よく使っていたListViewの代わりにしました.もちろん以前のListViewよりも機能が強すぎる気がします.しかし、現在のRecyclerViewには、addHeadView()とaddFooterView()の2つのリストコンポーネントでよく使用される機能が追加されていません.ネット上には、RecyclerViewにこの2つの機能を追加する方法を紹介するブログがたくさんあります.主に
onCreateViewHolder
とonBindViewHolder
で文章を作っています.追求のあるAndroid開発者として直接彼らを写すことはできません.自分の考えもいくつか書きます.だから私はListViewのソースコードに戻ってGoogleがどのようにこの機能を実現したのかを見ましたaddHeadView()ソース分析
ソースエントリ
2つのaddリロード方法は最後にここに来て、まず英語の注釈を見ます
/** * Add a fixed view to appear at the top of the list. If this method is * called more than once, the views will appear in the order they were * added. Views added using this call can take focus if they want. * <p> * Note: When first introduced, this method could only be called before * setting the adapter with {@link #setAdapter(ListAdapter)}. Starting with * {@link android.os.Build.VERSION_CODES#KITKAT}, this method may be * called at any time. If the ListView's adapter does not extend * {@link HeaderViewListAdapter}, it will be wrapped with a supporting * instance of {@link WrapperListAdapter}. * * @param v The view to add. * @param data Data to associate with this view * @param isSelectable whether the item is selectable */
public void addHeaderView(View v, Object data, boolean isSelectable) {}
まず方法の注釈部分を見て、英語の大まかな意味は:これはadapterにトップレベルのビューを追加する方法で、使用ヒントとパラメータの説明があります.
ListViewは、MVCモードモデル(model)−ビュー(view)−コントローラ(controller)ListView担当UIを用いて、ViewレイヤがAdapterを構築したときに入力されたDataデータがModelレイヤであり、データのソースであることを示す.Adapterアダプタは、ViewレイヤがどのようなUIを表示する必要があるかを制御し、最も重要なControllerレイヤです.
だからListViewにheadを追加するのは、実はadapterで修正することです.note:この方法は、バインドアダプタ
setAdapter()
の前に呼び出されることを示す.ソースコード
中のソースコードを見てみると、コードは多くありません.主に3段階に分けて操作する
public void addHeaderView(View v, Object data, boolean isSelectable) {
// list
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
mAreAllItemsSelectable &= isSelectable;
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter != null) {
//
// mAdapter HeaderViewListAdapter head、foot adapter
// HeaderViewListAdapter
if (!(mAdapter instanceof HeaderViewListAdapter)) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
//
// In the case of re-adding a header view, or adding one later on,
// we need to notify the observer.
if (mDataSetObserver != null) {
mDataSetObserver.onChanged();
}
}
}
FixedViewInfoクラス
HeadViewビューのパッケージで、3つのフィールドがパッケージされています.
/** * A class that represents a fixed view in a list, for example a header at the top * or a footer at the bottom. */
public class FixedViewInfo {
/** The view to add to the list */
public View view;
/** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */
public Object data;
/** <code>true</code> if the fixed view should be selectable in the list */
public boolean isSelectable;
}
HeaderView ListAdapterのソースコード分析
内部オブジェクト
クラスには3つのキー内部オブジェクトが保存されています
public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
// -->
private final ListAdapter mAdapter;
// These two ArrayList are assumed to NOT be null.
// They are indeed created when declared in ListView and then shared.
ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
// -->
// Used as a placeholder in case the provided info views are indeed null.
// Currently only used by some CTS tests, which may be removed.
// ArrayList<ListView.FixedViewInfo>
static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST =
new ArrayList<ListView.FixedViewInfo>();
boolean mAreAllFixedViewsSelectable;
private final boolean mIsFilterable;
コンストラクタ
初期化と付与を担当する3つのパラメータの構造関数
public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
ArrayList<ListView.FixedViewInfo> footerViewInfos,
ListAdapter adapter) {
mAdapter = adapter;
mIsFilterable = adapter instanceof Filterable;
if (headerViewInfos == null) {
// null new
mHeaderViewInfos = EMPTY_INFO_LIST;
} else {
mHeaderViewInfos = headerViewInfos;
}
if (footerViewInfos == null) {
mFooterViewInfos = EMPTY_INFO_LIST;
} else {
mFooterViewInfos = footerViewInfos;
}
mAreAllFixedViewsSelectable =
areAllListInfosSelectable(mHeaderViewInfos)
&& areAllListInfosSelectable(mFooterViewInfos);
}
headとfootビューのキーの追加
getViewで変更する
public View getView(int position, View convertView, ViewGroup parent) {
// Header (negative positions will throw an IndexOutOfBoundsException)
int numHeaders = getHeadersCount();
// position 0 view FixedViewInfo View
if (position < numHeaders) {
return mHeaderViewInfos.get(position).view;
}
// itemView mAdapter getView() BaseAdapter.getView(), ,
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getView(adjPosition, convertView, parent);
}
}
//foot Head
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).view;
}
その他の方法
一般的なadapterとはあまり違いはなく、私たちの分析点ではありません.