ラベル ListView の投稿を表示しています。 すべての投稿を表示
ラベル ListView の投稿を表示しています。 すべての投稿を表示

2012年4月12日木曜日

Android ListView でデータが空のときもヘッダー・フッターを表示する

ListView には addHeaderView()addFooterView() でヘッダーやフッターをつけることができます。

また、ListView にはリストのデータが空の時に表示させる emptyView を指定することができます。データがないときに画面が真っ黒になるとユーザーはアプリが壊れたと思ってしまうかもしれないので、空のときにはメッセージをだしましょうとよく言われます。

ただ、この emptyView を指定するとリストのデータが空のときに、ヘッダーやフッターも表示されなくなります。

emptyView を指定している状態でヘッダーやフッターを表示できるのか調べてみました。

まず、ListView で emptyView への切り替えをどこでしているかいうと AdapterView の updateEmptyStatus(boolean empty) です。

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/widget/AdapterView.java#717 717 private void updateEmptyStatus(boolean empty) { 718 if (isInFilterMode()) { 719 empty = false; 720 } 721 722 if (empty) { 723 if (mEmptyView != null) { 724 mEmptyView.setVisibility(View.VISIBLE); 725 setVisibility(View.GONE); 726 } else { 728 setVisibility(View.VISIBLE); 729 } 730 734 if (mDataChanged) { 735 this.onLayout(false, mLeft, mTop, mRight, mBottom); 736 } 737 } else { 738 if (mEmptyView != null) mEmptyView.setVisibility(View.GONE); 739 setVisibility(View.VISIBLE); 740 } 741 } ListView には setFilterText() でフィルターをセットできるのですが、このフィルターモードの場合はリストに表示するデータがなくても、フィルターに一致するデータがないというだけで実際のデータが空というわけではないので、最初の if 文で false にしています。

その次の if else 文が本体と emptyView の表示・非表示の切り替えをしているところです。
これをみると empty が true でも emptyView があれば本体が表示されることがわかります。

では、この updateEmptyStatus() がどこから呼ばれているかというと

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/widget/AdapterView.java#643
setEmptyView() 643 public void setEmptyView(View emptyView) { 644 mEmptyView = emptyView; 645 646 final T adapter = getAdapter(); 647 final boolean empty = ((adapter == null) || adapter.isEmpty()); 648 updateEmptyStatus(empty); 649 }

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/widget/AdapterView.java#717
checkFocus() 698 void checkFocus() { 699 final T adapter = getAdapter(); 700 final boolean empty = adapter == null || adapter.getCount() == 0; 701 final boolean focusable = !empty || isInFilterMode(); 705 super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState); 706 super.setFocusable(focusable && mDesiredFocusableState); 707 if (mEmptyView != null) { 708 updateEmptyStatus((adapter == null) || adapter.isEmpty()); 709 } 710 } の2カ所です。

いずれも adapter が null もしくは adapter.isEmpty() が true なら updateEmptyStatus() の引数として true が渡されています。

つまりまとめると

1. adapter != null && adapter.isEmpty == false → 本体が表示される
2. adapter == null or adapter.isEmpty == true
  → emptyView != null → 本体 が表示される
  → emptyView == null → emptyView が表示される

なので、結論としては、 isEmpty() で常に false を返すように Override するか、emptyView を null にすればよい。

ListView を単体で使うときは明示的に setEmptyView() するか、android/id:empty の View を XML で定義するので意識できるますが、Android で用意されている ListView 用の ListActivity と ListFragment を使うときにはちょっと注意が必要です。

Android 4.0 では、ListActivity でのデフォルトのレイアウトとして com.android.internal.R.layout.list_content_simple をセットしています。

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/app/ListActivity.java#308 308 private void ensureList() { 309 if (mList != null) { 310 return; 311 } 312 setContentView(com.android.internal.R.layout.list_content_simple); 313 314 }
http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/res/res/layout/list_content_simple.xml 20
ちなみに Android 2.3.4 では、com.android.internal.R.layout.list_content をセットしていますが、なかのレイアウトは 4.0 の list_content_simple と同じです。

http://tools.oesf.biz/android-2.3.4_r1.0/xref/frameworks/base/core/java/android/app/ListActivity.java#308 308 private void ensureList() { 309 if (mList != null) { 310 return; 311 } 312 setContentView(com.android.internal.R.layout.list_content); 313 314 }
http://tools.oesf.biz/android-2.3.4_r1.0/xref/frameworks/base/core/res/res/layout/list_content.xml 20 <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" 21 android:layout_width="match_parent" 22 android:layout_height="match_parent" 23 android:drawSelectorOnTop="false" 24 />
一方、ListFragment のデフォルトのレイアウトとしては com.android.internal.R.layout.list_content がセットされています。

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/app/ListFragment.java#191 190 @Override 191 public View onCreateView(LayoutInflater inflater, ViewGroup container, 192 Bundle savedInstanceState) { 193 return inflater.inflate(com.android.internal.R.layout.list_content, 194 container, false); 195 }
こっちはちょっと複雑なレイアウトになっています。

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/res/res/layout/list_content.xml 18 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 19 android:layout_width="match_parent" 20 android:layout_height="match_parent"> 21 22 <LinearLayout android:id="@+id/progressContainer" 23 android:orientation="vertical" 24 android:layout_width="match_parent" 25 android:layout_height="match_parent" 26 android:visibility="gone" 27 android:gravity="center"> 28 29 <ProgressBar style="?android:attr/progressBarStyleLarge" 30 android:layout_width="wrap_content" 31 android:layout_height="wrap_content" /> 32 <TextView android:layout_width="wrap_content" 33 android:layout_height="wrap_content" 34 android:textAppearance="?android:attr/textAppearanceSmall" 35 android:text="@string/loading" 36 android:paddingTop="4dip" 37 android:singleLine="true" /> 38 39 </LinearLayout> 40 41 <FrameLayout android:id="@+id/listContainer" 42 android:layout_width="match_parent" 43 android:layout_height="match_parent"> 44 45 <ListView android:id="@android:id/list" 46 android:layout_width="match_parent" 47 android:layout_height="match_parent" 48 android:drawSelectorOnTop="false" /> 49 <TextView android:id="@+android:id/internalEmpty" 50 android:layout_width="match_parent" 51 android:layout_height="match_parent" 52 android:gravity="center" 53 android:textAppearance="?android:attr/textAppearanceLarge" /> 54 </FrameLayout> 55 56 </FrameLayout>

注目してほしいのが @+android:id/internalEmpty という ID の TextView です。
ListFragment には setEmptyText() という、データが空のときに表示する文字をセットするメソッドが用意されています。このメソッドが呼ばれると、次のように ListView の setEmptyView() が呼ばれます。

http://tools.oesf.biz/android-4.0.1_r1.0/xref/frameworks/base/core/java/android/app/ListFragment.java#289 289 public void setEmptyText(CharSequence text) { 290 ensureList(); 291 if (mStandardEmptyView == null) { 292 throw new IllegalStateException("Can't be used with a custom content view"); 293 } 294 mStandardEmptyView.setText(text); 295 if (mEmptyText == null) { 296 mList.setEmptyView(mStandardEmptyView); 297 } 298 mEmptyText = text; 299 }
ここの mStandardEmptyView というのが上記の @+android:id/internalEmpty という ID の TextView に対応しています。


ということで、ListFragment でなんとなくやってた setEmptyText() をコメントアウトしたらヘッダーでるようになったー!

ただし、残念ながらこの場合も

-----
ヘッダー
empty message
フッター
-----

のようにはできないです。ヘッダー・フッターと emptyView は一緒に出すことはコードを見た限りではできないですねー

updateEmptyStatus が protected だったらいろいろできたのに。。。

やるとしたらこんな感じかな。
ヘッダーと、emptyView を同じレイアウトXMLから生成するくらいしか方法がないかな。

public class MainActivity extends ListActivity implements View.OnClickListener{ ArrayAdapter<String> mAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1); LayoutInflater inflater = getLayoutInflater(); View header = inflater.inflate(R.layout.header, null, false); getListView().addHeaderView(header); setListAdapter(mAdapter); View emptyHeader = getListView().getEmptyView(); emptyHeader.setOnClickListener(this); header.setOnClickListener(this); } @Override public void onClick(View v) { if(mAdapter.isEmpty()) { mAdapter.add("Test"); } else { mAdapter.remove("Test"); } } } <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:drawSelectorOnTop="false" /> <LinearLayout android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <include layout="@layout/header"/> <TextView android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:gravity="center" android:text="No data" android:textSize="30sp" /> </LinearLayout> </FrameLayout> <?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/header" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Header" /> ListFragment でも同じ感じ。

public class MainFragment extends ListFragment implements View.OnClickListener { ArrayAdapter<String> mAdapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.main, container, false); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1); LayoutInflater inflater = getActivity().getLayoutInflater(); View header = inflater.inflate(R.layout.header, null, false); getListView().addHeaderView(header); setListAdapter(mAdapter); View emptyHeader = getListView().getEmptyView(); emptyHeader.setOnClickListener(this); header.setOnClickListener(this); } @Override public void onClick(View v) { if(mAdapter.isEmpty()) { mAdapter.add("Test"); } else { mAdapter.remove("Test"); } } }

もちろん Adapter を extends して isEmpty() で true を返すようにすれば emptyView がセットされていても本体が表示されるようになります。 具体的な用途は思いつかないですが、データのあるなしにかかわらず独自の基準で emptyView の表示・非表示を切り替えたい場合には便利だと思います。


ちなみに、ListFragment で emptyView を使う場合ははまりポイントがいっぱいなので、 このエントリを見ておくことをオススメします!
Y.A.M の 雑記帳: Android ListFragment でカスタムレイアウトを使うと setEmptyText() が使えない -





2010年11月4日木曜日

Android Adapter & ListView & ExpandableListView

第3回デザイン部勉強会で Adapter (と関連する ListView ,ExpandableListView)について話しました。

資料です。



これようのサンプルアプリも作ったので、
こちらからどうぞ

https://github.com/yanzm/AdapterSamples



 

2010年9月1日水曜日

Android 「The world of ListView」 - Gotchas and don’ts -

Google I/O の 「The world of ListView」というセッションを見たので
そのまとめ。

長いので、項目ごとに分けました。
今回は 「Gotchas and don'ts」

--------------------------------------

Google I/O の「The world of ListView」のページは こちら

セッションのスライドはこちら

 agenda

  • Virtualization and adapters

  • Item properties

  • Headers and footers

  • List selectors

  • Other features

  • Gotchas and don'ts


--------------------------------------

■ Gotchas and don'ts (落とし穴とやっちゃいけないこと)

# gotchas って単語しらなかった。「落とし穴」なんだね。

 * Gotcha(落とし穴)

  ・リストが真っ黒になった?!
    • 最適化に便利なので...
      – スクロール中の view が bitmap でキャッシュされてるとき
      – ブレンディングを避けるために不透明の bitmap を使っている
    • 解決方法
      – android:cacheColorHint="#00000000"
      – android:cacheColorHint
         ="@color/myBackgroundColor"

  ・スクロールバーのサイズが変わった?!
    • view がすごく異なる高さを持つときにおこる
    • Smooth scrollbar は各要素(item)の高さが必要
      – Too expensive(コストかかりすぎ!)
    • 解決方法
      – android:smoothScrollbar=”false”



 * Don't (やっちゃいけないこと)

  ・android:layout_height=”wrap_content”
    • ListView は仮想化されている
    • wrap_content = 子要素の最大
      – ListViewは均等サイズの子要素に対応
      – 数千個の子要素を測る?
    • Android framework cheats
      – 3個の子要素だけ測る
      – それでもコストかかりすぎ
    •間違った結果になる

  ・ScrollView の中に ListView を入れる
    • ScrollView がスクロールする
    • ListView がスクロールする
    • どれがスクロールする?

  ・adapter に view をキャッシュする
    • ListView の裏をかこうとしない
      – ListView は view の所有権とコントロールを前提としている
    • 複雑な再利用メカニズム
      – 多数の最適化
      – 我々も時にはそこにバグを残してしまう
    • 最悪の場合はアンデッド
      – 再利用者と画面の両方に view

  ・必要でないときに ListView を使う
    • ListView は...
      – 再帰的な、境界のないデータ用
      – (たくさんの)複雑さが加わる
    • LinearLayout や ScrollView では置き換えられない?


   

Android 「The world of ListView」 - Other features -

Google I/O の 「The world of ListView」というセッションを見たので
そのまとめ。

長いので、項目ごとに分けました。
今回は 「Other features」

--------------------------------------

Google I/O の「The world of ListView」のページは こちら

セッションのスライドはこちら

 agenda

  • Virtualization and adapters

  • Item properties

  • Headers and footers

  • List selectors

  • Other features

  • Gotchas and don'ts


--------------------------------------

■ Other features

 * Transcript and stack from bottom

   • android:transcriptMode
     – コンテンツが変わったときのリストの振る舞い
     – "disabled", スクロールしない
     – "normal", 最後の要素が見えているなら、底部までスクロールする
     – "alwaysScroll", いつも底部までスクロールする

   • android:stackFromBottom
     – 要素を逆順にスタックする
     – adapter の最後の要素からスタートする

   • チャットなどにいい
     – Messaging, Talk, IRC, etc.




 * Text filter

   • android:textFilterEnabled="true"
   • adapter は Filterable を実装する必要がある
     – CursorAdapter 、 ArrayAdapterなど
     – getFilter() を実装する
   • Filter を実装する


// Filters the content of the adapter on a worker thread
protected FilterResults performFiltering(CharSequence prefix)

// Displays the results on the UI thread
protected void publishResults(CharSequence constraint, FilterResults results)


   CursorAdapter や ArrayAdapter のコードをみるのがいいらしい

2010年8月30日月曜日

Android 「The world of ListView」 - List selectors -

Google I/O の 「The world of ListView」というセッションを見たので
そのまとめ。

長いので、項目ごとに分けました。
今回は 「List selectors」

--------------------------------------

Google I/O の「The world of ListView」のページは こちら

セッションのスライドはこちら

 agenda

  • Virtualization and adapters

  • Item properties

  • Headers and footers

  • List selectors

  • Other features

  • Gotchas and don'ts


--------------------------------------

List selectors

 • 選択中のアイテムをハイライト
 • タッチモードでは表示されない
   – タッチモードには選択中がない!
 • リスト要素の背後に表示
   – android:drawSelectorOnTop="true" にすると前に表示される





<selector>
<item android:state_window_focused="false"
android:drawable="@color/transparent" />

<item android:state_focused="true" android:state_enabled="false"
android:state_pressed="true"
android:drawable="@drawable/list_selector_background_disabled" />

<item android:state_focused="true" android:state_enabled="false"
android:drawable="@drawable/list_selector_background_disabled" />

<item android:state_focused="true" android:state_pressed="true"
android:drawable="@drawable/list_selector_background_transition" />

<item android:state_focused="false" android:state_pressed="true"
android:drawable="@drawable/list_selector_background_transition" />

<item android:state_focused="true"
android:drawable="@drawable/list_selector_background_focus" />
</selector>


 要素(項目)が不透明な場合は、selector drawable を使う
  – convertView.setBackground(R.drawable.selector)


<selector>
<item android:state_selected="true"
android:drawable="@color/transparent" />

<item android:state_selected="false"
android:drawable="#ff00ff00" />
<selector/>

2010年8月27日金曜日

Android 「The world of ListView」 - Headers and footers -

Google I/O の 「The world of ListView」というセッションを見たので
そのまとめ。

長いので、項目ごとに分けました。
今回は 「Headers and footers」

--------------------------------------

Google I/O の「The world of ListView」のページは こちら

セッションのスライドはこちら

 agenda

  • Virtualization and adapters

  • Item properties

  • Headers and footers

  • List selectors

  • Other features

  • Gotchas and don'ts


--------------------------------------

Headers and footers



 * Fixed

   fixed header/footer は簡単。次のように
   LinearLayout でOK


<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">

<!-- ... -->

</LinearLayout>

<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0" />

</LinearLayout>



 * Scrolling

  一緒にスクロールする header/footer はメソッドが用意されている
  twitter の reload / more load みたいなやつ。

  • ListView.addHeaderView()
  • ListView.addFooterView()
  • setAdapter() の前に呼ばなければならない
  • isSelectable == Adapter.isEnabled()
    – Sorry, our bad(混乱する名前にしちゃってごめんね。。。)

  addHeaderView() と addFooterView() は isSelectable という
  パラメータを保持している。
  これは、使われている final adapter が items が有効になっている
  リストに report back するかどうかに対応する。
  「ちょっと混乱する名前だね」って言ってた。

  (This corresponds to whether or not the final adapter
   being used will report back to the list that these
   items are enabled.)

 * Wrapped adapter

  ListView では、内部的に別の adapter の中に your adapter を
  wrapping することで、scrolling header / footer を実現している。
  そのため、最初の最後の要素(item)では、異なるタイプの view を返す。
  よって、setAdapter で渡した adapter と getAdapter
  で返ってくる adapter は異なる。ちょっと注意が必要。


ListView list = ...;
list.addHeaderView(myHeader);
list.addFooterView(myFooter);
list.setAdapter(myAdapter);

boolean same = list.getAdapter() == myAdapter;
// same == false!
// getAdapter() returns a
// android.widget.HeaderViewListAdapter

2010年8月26日木曜日

Android 「The world of ListView」 - Item properties -

Google I/O の 「The world of ListView」というセッションを見たので
そのまとめ。

長いので、項目ごとに分けました。
今回は 「Item properties」

--------------------------------------

Google I/O の「The world of ListView」のページは こちら

セッションのスライドはこちら

 agenda

  • Virtualization and adapters

  • Item properties

  • Headers and footers

  • List selectors

  • Other features

  • Gotchas and don'ts


--------------------------------------

Item properties

 * Enabled or disabled

   • Enabled
     – 選択、クリックができる要素
   • Disabled
     – コンテンツ内の区切り線・ヘッダ

   • 例)マーケットアプリ
     緑が Disabled Items



 * Choice mode
   • Single choice mode (radio buttons)
   • Multiple choice mode (checked items)
   • 選択されているのはどれ?
     – Single choice mode
       • getCheckedItemPosition()
     – Multiple choice mode
       • getCheckedItemPositions()
     – Stable IDs はポジションが変化するような場合に役立つ
       • getCheckedItemIds()
       • Stable ID は項目の挿入や削除によって変化しない
       (ポジションは変わる)
       • an integer

   • 例)左:Single choice mode, 右:Multiple choice mode





 * Focusable
   • setItemsCanFocus(boolean itemsCanFocus)
   • itemsCanFocus = false : リストの要素全体はフォーカスできる
   • itemsCanFocus = true : リストの要素内の view にフォーカスできる

   # 「UIで大きな制限の1つが、トラックボールとタッチスクリーン両方を
   # サポートしなければならないということ。
   # タッチしたら、フォーカスや選択はすぐ消えるように、早い段階に決めた。
   # なぜなら、choice mode があるから。
   # ユーザーがリスト内の項目をタップして、かつ画面上の選択を
   # 維持させることはできない。
   # ListViewは本当に難しいこと発生させないようにコントロールしている。

   # 例えば、1つの行に複数のボタンが含まれているけれども、
   # トラックボールを使った場合、行全体が選択される。
   # その理由は、行全体を選択している状態から、その中の小さい要素を
   # 選択するというトラックボールナビゲーションを持つことは、
   # とてもやっかいだから。」

   もし、行の中の小要素(ボタンとか、リンク)にフォーカスさせないなら
   itemCnaFocus = true にする。

   • 例)右:itemsCanFocus = false, 左 : itemsCanFocus = true



 # Item の view が複雑になると、この Focusable をどっちにするかは
 # 悩ましいところ。登壇者も、いいアイディアがあればコミュニティに
 # フィードバックしてほしいと言ってました。
 # 将来的に改善したいとも言ってたので、期待したいです。

2010年8月24日火曜日

Android 「The world of ListView」 - Virtualization and adapters -

Google I/O の 「The world of ListView」というセッションを見たので
そのまとめ。

長いので、項目ごとに分けました。
今回は 「Virtualization and adapters」

--------------------------------------

Google I/O の「The world of ListView」のページは こちら

セッションのスライドはこちら

 agenda

  • Virtualization and adapters

  • Item properties

  • Headers and footers

  • List selectors

  • Other features

  • Gotchas and don'ts

--------------------------------------

■ Virtualization and adapters

 ・ Virtualization
  * 問題点 : 巨大なデータセット
   ・メモリ
   ・パフォーマンス
  
  10,000 item くらいの(ってセッションでは言ってた)データを
  比較的速く扱うには?
  普通は、10,000 個のview を view の階層に添付したくはないよね。
  そのために、、、

  * 解決方法
   ・必要に応じでデータを格納
   ・view をリサイクルして、オブジェクトのチャーン(object churn)を減らす
  

 ・ Adapters
  * 用語
   – index: 子要素
   – position: adapter 内のデータ
   – id: データの識別子

  * Stable IDs
   – hasStableIds() == true で調べる
   – 常に同じ値を参照するための ID
   – ListView に役立つ!!

  * getView(int position, View convertView, ViewGroup parent)
   – 全データの表示を制御
   – 最適化
   – はまりやすい!「Shoot yourself in the foot (and the face)」

  ローカルのデータや、データベースのデータや、ネットワークから
  とったデータ、から割り当てたデータソースから、データを取り出す。
  view は単純な TextView だったり、複雑なレイアウトだったりする。
  
 
  * getView の 最適化ポイント
   • ListView is smart
   • convertView
    – ListView で提供される
    – 要素(item)のタイプと一致
    – 再利用すべし!!

   extra view パラメータの呼び出しを convert view に
   渡してしまえばOK。ListView がスクリーン外の view を
   再利用する方法と同じ最適化方法。
   
   ListView はスクリーン外へ移動した全部の extra view を
   keep track して、既存のデータを入れてから返す。
   これが、convert view parameter。
   つまり、自動的に item のタイプを match up している。
   もし、adapter 内に異なるデータによる複数のタイプ
   (例えば、画像と文字)がある場合、ListViewに adapter
   のあるポジションがどのタイプか聞いたとき convert view は
   いつも正しいタイプになっている(必要がある)。
   でもこれはあんまり賢いやりかたじゃない。
   
   だから、
    もし convertView が null じゃないなら、再利用する!
   

   ● getView のダメな使い方 (The Slow Way)


public View getView(int position, View convertView, ViewGroup parent) {
View item = mInflater.inflate(R.layout.list_item_icon_text, null);
((TextView) item.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) item.findViewById(R.id.icon)).setImageBitmap(
(position & 1) == 1 ? mIcon1 : mIcon2);
return item;
}

    getView 内で毎回 view を inflate してはダメ!
    xml を毎回 parse することは、メモリもCPUも使うので
    とっても無駄が多い。


   ● getView の普通の使い方 (The Right Way)


public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.item, parent, false);
}
((TextView) convertView.findViewById(R.id.text)).setText(DATA[position]);
((ImageView) convertView.findViewById(R.id.icon)).setImageBitmap(
(position & 1) == 1 ? mIcon1 : mIcon2);
return convertView;
}

    最初だけ view を inflate して、それを再利用する


   ● getView の賢い使い方 (The Fast Way)

   ViewHolder を使うべし


static class ViewHolder {
TextView text;
ImageView icon;
}



public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;

if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_icon_text, parent, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);

convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}

holder.text.setText(DATA[position]);
holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);

return convertView;
}

    最初だけ view を inflate して、holder を介して再利用する


    このくらい違う




   * How to shoot yourself in the foot (どのようにはまりやすいか)
     • ロカールビューのキャッシュ
     • adapter からビューにアクセスする
     • convertView の構造を変える
     • getView の呼び出しについての仮定

   * データの変更を制御する
    • notifyDataSetChanged()
     – データの新規作成 or 更新
    • notifyDataSetInvalidated()
     – アクセスできるデータがないとき

   * 異なるビュータイプを制御する
    • 要素のタイプ (item types) を Built-in にする
    • getItemViewType
     – 与えられたポジションのビューのタイプを取得
     – 正しい convertView を提供するのに使う
    • getViewTypeCount
     – 予測されるタイプの数を取得

   * slow data sources を制御する
    • UIスレッドで adapter の変更 (modification)
    • Fetching data can happen anywhere
    • 別のスレッド上でデータをリクエストする
    • UIスレッドで、adapter の変更をコミットする
    • notifyDataSetChanged() を呼び出す

 書きかけだけど、一旦出します。
 もうちょっと追記するかも。