さまざまなアダプターを開発して使用した結果、私が最も快適に使用できるのは BaseAdapter です。他のアダプターに比べて使用が少し面倒ですが、これを使用すると、ListView、GridView、ギャラリー、スピナーなど。 BaseAdapter を使用する場合は、多くのメソッドを書き直す必要があります。その中で最も重要なのは、ListView の最適化などの問題に関係するため、他のメソッドについては、リンク先の記事を参照してください
BaseAdapter とその他のアダプターは少し異なります。他のアダプターは、
SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.list_item, new String[]{"img","title","info",newint[]{R.id.img, R.id.title, R.id.info}});
などの構築メソッドで直接データを設定できます。ただし、BaseAdapter では、BaseAdapter から継承したクラスを実装し、その中の多くのメソッド (
など) を書き直す必要があります。class MyAdapter extends BaseAdapter { private Context context; public MyAdapter(Context context) { this.context = context; } @Override publicint getCount() { // How many items are in the data set represented by this Adapter.(在此适配器中所代表的数据集中的条目数) return0; } @Override public Object getItem(int position) { // Get the data item associated with the specified position in the data set.(获取数据集中与指定索引对应的数据项) returnnull; } @Override publiclong getItemId(int position) { // Get the row id associated with the specified position in the list.(取在列表中与指定索引对应的行id) return0; } @Override public View getView(int position, View convertView, ViewGroup parent) { // Get a View that displays the data at the specified position in the data set. returnnull; } }
this 難しいことはありませんが、この getView メソッドは慎重に扱う必要があり、これが最も面倒です。最初のタイプ: 処理がないため、このように記述することはお勧めできません。データ量が少ない場合は問題ありませんが、リストアイテムのデータ量が多い場合、毎回ビューの再作成やリソースの設定が行われ、パフォーマンスに重大な影響を与えるため、やめてください。最初からこのメソッドを使用しないでください
@Override public View getView(int position, View convertView, ViewGroup parent) { View item = mInflater.inflate(R.layout.list_item, null); ImageView img = (ImageView)item.findViewById(R.id.img) TextView title = (TextView)item.findViewById(R.id.title); TextView info = (TextView)item.findViewById(R.id.info); img.setImageResource(R.drawable.ic_launcher); title.setText("Hello"); info.setText("world"); return item; }
2 番目のメソッド ListView の最適化: ConvertView をキャッシュすることで、キャッシュされた contentView を使用するこのメソッドは、ビューを作成する前にビューがキャッシュに存在するかどうかを判断できます。すでに存在する場合は、それを使用できます。 View をキャッシュに入れてパフォーマンスを向上させます
public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null) { convertView = mInflater.inflate(R.layout.list_item, null); } ImageView img = (ImageView)convertView.findViewById(R.id.img) TextView title = (TextView)convertView.findViewById(R.id.title); TextView info = (TextView)ConvertView.findViewById(R.id.info); img.setImageResource(R.drawable.ic_launcher); title.setText("Hello"); info.setText("world"); return convertView; }
3 番目の ListView の最適化: ConvertView +ViewHolder を使用して実現します。ViewHolder は静的クラスです。ViewHolder を使用する主な利点は、データを表示するビュー (View) をキャッシュし、 UIの応答速度。
convertView == null と判定した場合、空の場合は、設計されたListの項目レイアウト(XML)に従ってconvertViewに値を代入し、convertView(XML)内の各ViewコントロールをバインドするviewHolderを生成します。レイアウト内のそれらのコントロール)。次に、convertView の setTag を使用して viewHolder をタグに設定し、システムが 2 回目に ListView を描画するときにタグからそれを取り出せるようにします。 (以下のコードを参照)
convertView が空でない場合、convertView の getTag() を直接使用して ViewHolder を取得します。
//在外面先定义,ViewHolder静态类 staticclass ViewHolder { public ImageView img; public TextView title; public TextView info; } //然后重写getView @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if(convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.list_item, null); holder.img = (ImageView)item.findViewById(R.id.img) holder.title = (TextView)item.findViewById(R.id.title); holder.info = (TextView)item.findViewById(R.id.info); convertView.setTag(holder); }else { holder = (ViewHolder)convertView.getTag(); holder.img.setImageResource(R.drawable.ic_launcher); holder.title.setText("Hello"); holder.info.setText("World"); } return convertView; }
この時点で、ViewHolder 静的クラスとキャッシュ ConvertView の組み合わせと、convertView を直接使用することの違いは何かと尋ねる人がいるかもしれません。ここでは、公式の説明が与えられています
Adapter を改善するための 2 つの方法
ここで実装されたアダプターは 2 つの手法を使用します: - getView() に渡された ConvertView を再利用して、不要なときに View がインフレートされるのを回避します
(訳: getView() メソッドに渡されたキャッシュ ConvertView を再利用して、不要なビューが埋められるのを回避します) -不必要な場合に findViewById() を呼び出すのを避けるための ViewHolder パターン
(翻訳: FindViewById() への不必要な呼び出しを避けるために ViewHolder パターンを使用します: findViewById が多すぎるとパフォーマンスにも影響するため) ViewHolder クラスの役割 - ViewHolderパターンは、getView() によって返されるビューのタグにデータ構造を格納することで構成されます。このデータ構造には、データをバインドするビューへの参照が含まれているため、getView() が呼び出されるたびに findViewById() を呼び出す必要がなくなります
(翻訳: ViewHolder モードは、getView() メソッドによって返されるビューのタグにデータ構造を保存します。このデータ構造には、データをバインドしたいビューへの参照が含まれているため、毎回 getView を呼び出す必要がなくなります () findViewById() を呼び出すとき)
例 1: BaseAdapter を使用して ListView レイアウト
main をカスタマイズします。Gallery に BaseAdapter
main.xml
<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <ListView android:id="@+id/lv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:fastScrollEnabled="true" /> </LinearLayout>
Activity を適用します: この部分の getView は最適化されておらず、長時間のデバッグ後に調整されましたが、当面は最も基本的な方法が使用されます。画像リソースが多いとメモリ不足エラーが発生するため、ギャラリーのメモリ リークについては特別な時間を見つけて書きます
<?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="20sp" /> <TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="14sp" /> </LinearLayout> </LinearLayout>
動作効果: 原理は同じですが、レイアウトは読み込まれていますが、この小さな違いだけでも十分迷惑です