1. ホーム
  2. アンドロイド

Androidのパフォーマンス。クラシックな ListView アダプタ convertView のキャッシュと再利用メカニズム

2022-02-28 12:10:33
Androidのパフォーマンス。Classic ListView アダプタ convertView のキャッシュと再利用メカニズム

AndroidのListViewの一般的なアダプタは、主にListViewのアイテムビューの読み込み効率を上げるために、試行されたビューをキャッシュするために使用されるconvertViewを使用しています。convertViewを使用する主な目的は、ListViewのアイテムビューのロード効率を向上させるために使用されるattemptViewをキャッシュすることです。経験豊富なAndroid開発者は通常、アダプタのgetViewで、最初にconvertViewがNULLかどうかを判断し、それがNULLではない場合、直接convertViewを再度、それ以外は新しいビューを作成していることを知っていますか?以前の付録記事1を参照してください。
(a) AndroidのListViewの初期化を初めて開くとき、この時のAdapterでは間違いなくconvertViewは全て空ですが、Androidは新しいconvertViewを作成しますが、いくつ作成されるのでしょうか。答えは、画面のListViewのアイテムの数だけconvertViewを作成することです、これはListViewがアイテムを表示するために初期化された最初の時間だけであることに注意してください、これはArrayAdapterで構成されたListViewにconvertViewを作成するメカニズムです、例を書きます。

パッケージ zhangphil.demo; インポートandroid.app.ListActivity; import android.os.Bundle; import android.support.annotation.NonNull; Nullable; import android.support.annotation.NonNull; import android.support.annotation.NonNull;Nullable import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; public class MainActivity extends ListActivity { (パブリッククラス メインアクティビティ エクステンド リストアクティビティ) private int tagId = 0; オーバーライド protected void onCreate(Bundle savedInstanceState) { . super.onCreate(savedInstanceState)を実行します。 ArrayAdapter mAdapter = new ArrayAdapter(this, 0) { { ArrayAdapter mAdapter = new ArrayAdapter(this, 0) { 配列アダプタを作成します。 private TextView text1; private TextView text2; 非Null オーバーライド public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {... if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.simple_list_item_2, null)を実行します。 //convertView.setMinimumHeight(400); Log.d("position" + position, "Create new convertView, set tagId:" + tagId)を実行します。 convertView.setTag(tagId++)を実行します。 } else { Log.d("position" + position, convertView.getTag() + " reuse convertView")を実行します。 text1 = convertView.findViewById(android.R.id.text1); text1.setTextColor(getResources().getColor(android.R.color.holo_blue_bright)).android.R.id; text1.setText(getItem(position))。 text2 = convertView.findViewById(android.R.id.text2); text2.setTextColor(getResources().getColor(android.R.color.holo_red_light)); text2.setText("convertView tagId:" + String.valueOf(convertView.getTag())); return convertView; } Nullable オーバーライド public String getItem(int position) { (アイテム) return "位置 position:" +位置。 } オーバーライド public int getCount() { 99999を返します。 } }; setListAdapter(mAdapter); } }

convertViewにタグを付けるためにtagIdを定義し、新しく作成されたconvertViewにそれを入力し、その時点でどのconvertViewが実際に再利用されているかを追跡するために、その後の再利用の際にそれを取り出します。

コードは以下のように実行されます。





logcatのログ出力です。

11-03 14:40:08.745 22766-22766/zhangphil.demo D/Position 0: Create new convertView, set tagId:0
11-03 14:40:08.760 22766-22766/zhangphil.demo D/Location 1: Create new convertView, set tagId:1
11-03 14:40:08.765 22766-22766/zhangphil.demo D/Location 2: Create new convertView, set tagId:2
11-03 14:40:08.773 22766-22766/zhangphil.demo D/Location 3: Create new convertView, set tagId:3
11-03 14:40:08.782 22766-22766/zhangphil.demo D/Location 4: Create new convertView, set tagId:4
11-03 14:40:08.787 22766-22766/zhangphil.demo D/Location 5: Create new convertView, set tagId:5
11-03 14:40:08.795 22766-22766/zhangphil.demo D/Location 6: Create new convertView, set tagId:6
11-03 14:40:08.800 22766-22766/zhangphil.demo D/Location 7: Create new convertView, set tagId:7
11-03 14:40:16.573 22766-22766/zhangphil.demo D/location 8: Create new convertView, set tagId:8



ListViewの初期化段階で、Androidは計算後に9つの新しいconvertViewを作成し、現在のデバイス画面の可視領域に8つよりも1つ多いことがわかります。これらの9つの新しいconvertViewにそれぞれtagId 0,1,2,3,4,5,6,7,8 とタグ付けしました。これらのタグIDは入力された これらのタグIDは後で追跡してconvertViewの特定の再利用を見ることができます。
ここで注意! 各画面のサイズやアダプタの getView が返す View の高さによって、 新たに作成される convertView の数は端末ごとに異なります。
(b) convertViewが活躍するのは、ListViewが上下にスワイプされた時で、convertViewのキャッシュと再利用のメカニズムが活躍します。例えば、ListViewを画面上で下から上へ指ではじくと、ListViewの先頭にあるアイテムがデバイスの画面から転がり落ち、下にある新しいアイテムが読み込まれますが、この時にConvertViewの多重化メカニズムが発揮されます。ListViewの初期化段階で9つの新しいconvertViewが作成されているので、AndroidシステムはListViewの初期化段階で作成された9つの新しいconvertViewを全てキャッシュし、ListViewを上下に反転させると、それまで上下に表示していたアイテムがデバイスの画面からロールアウトするようになっています。このように、AndroidシステムはこれらのconvertViewを完全にリサイクルするか、再利用するかのどちらかになります。listViewのアイテムには共通点があります。ほとんどの場合、これらのアイテムのViewは同じなので、再利用を続けることが賢明で、システムの読み込みパフォーマンスが向上することは間違いありませんが、新しいconvertViewが新しく作られるたびに、ある程度のシステムのオーバーヘッドがあることが分かっています。そこで、ListViewを下に反転させると、図のようなコードが実行されます。






logcatのログ出力はこのようになります。
11-03 15:02:50.553 31901-31901/zhangphil.demo D/location 64: 1 Multiplexing convertView
11-03 15:02:50.637 31901-31901/zhangphil.demo D/location 65: 2 Reusing convertView
11-03 15:02:50.720 31901-31901/zhangphil.demo D/Location 66: 5 Reusing convertView
11-03 15:02:50.820 31901-31901/zhangphil.demo D/Location 67: 4 Reusing convertView
11-03 15:02:50.936 31901-31901/zhangphil.demo D/Location 68: 7 Multiplexing convertView
11-03 15:02:51.069 31901-31901/zhangphil.demo D/location 69: 3 Multiplexing convertView
11-03 15:02:51.236 31901-31901/zhangphil.demo D/Location 70: 8 Reusing convertView
11-03 15:02:51.452 31901-31901/zhangphil.demo D/location 71: 0 reusing convertView
11-03 15:02:51.786 31901-31901/zhangphil.demo D/location 72: 6 Multiplexing convertView



(c) (b)項の記述とコード実行の出力から、AndroidのListViewは、convertViewの再利用の各ラウンドで、tagId.tagIdを出力することから分かるように、キャッシュされたconvertViewの再利用の際に、順番に再利用することが保証されていないことが分かります。出力の順番は厳密に0,1,2,3,4,5,6,7,8ではなく、多少ランダムですが、唯一保証できることは、再利用の順番が決まっていないだけで、それぞれのラウンドで確実に0-8のタグID番号の9つのキャッシュされたconvertViewを使い切ると言うことです。もし、キャッシュされた9つのconvertViewsを特定の順番で再利用したい場合は、getViewで新しいconvertViewsを作成するときに、リンクチェーン(閉ループの輪の鎖)に入れることができます。開発者は、getViewがconvertViewが空だと判断した時点からのリンクチェーンの長さを、特定の状況に応じて定義することができます。
付録
1, "AndroidのListViewにおけるItem Viewの読み込み効率を向上させる"ViewHolder"の技術に基づく; link: http://blog.csdn.net/zhangphil/article/details/ 44779723