[解決済み] ListViewのリサイクル機構の仕組み
質問
というわけで、以前にもあったこの問題が発生し、当然ながら私は
ここで
. Luksprogの回答は、ListViewとGridViewがどのようにViewをリサイクルしながら最適化されるかについて全く知らなかったので、素晴らしいものでした。そのため、彼のアドバイスにより、GridViewにViewを追加する方法を変更することができました。問題は、今、私は意味をなさない何かを持っているということです。これは私の
getView
から
BaseAdapter
:
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
convertView = inflater.inflate(R.layout.day_view_item, parent, false);
}
Log.d("DayViewActivity", "Position is: "+position);
((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);
//layout.addView(new EventFrame(parent.getContext()));
TextView create = new TextView(DayViewActivity.this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
create.setLayoutParams(params);
create.setBackgroundColor(Color.BLUE);
create.setText("Test");
//the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
//new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)
if(position == 0) {
Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
layout.addView(create);
}
return convertView;
}
}
問題は、私がスクロールするとき、これが起こる、そして、位置0にない...。ポジション6とポジション8のように見え、さらにポジション8には2つ置かれます。今私はまだListViewとGridViewを使うコツを掴もうとしているので、なぜこれが起こるのか理解できません。この質問をする主な理由の一つは、おそらくListViewとGridViewのリサイクルビューについて知らない他の人を助けるため、または、この方法 記事 は、ScrapViewメカニズムについて説明しています。
後編集
ListViewの仕組みを理解するために基本的に必要なgoogle IO talkへのリンクを追加しました。リンクはコメント欄で切れていました。そこで、user3427079さんがリンクを更新してくれました。 ここに で、簡単にアクセスできます。
どのように解決するのですか?
当初は私もリストビューのリサイクルやconvertviewの使用メカニズムについて知りませんでしたが、丸一日かけて調べた結果、以下の画像を参照することでリストビューのメカニズムがほぼ理解できました。 android.amberfog
リストビューがアダプタによって満たされるときはいつでも、基本的には、リストビューに表示される 行数 を表示し、リストをスクロールしても行数は増えません。これは android が listview をより効率的かつ高速に動作させるために使用しているトリックです。 さて、画像を参照しながらリストビューの内部を説明すると、ご覧の通り、リストビューは最初は7つのアイテムが表示されています。そして、アイテム1が見えなくなるまでスクロールアップすると、 getView() はこのビュー(つまりアイテム1)をリサイクラーに渡して
System.out.println("getview:"+position+" "+convertView);
あなたの中の
public View getView(final int position, View convertView, ViewGroup parent)
{
System.out.println("getview:"+position+" "+convertView);
ViewHolder holder;
View row=convertView;
if(row==null)
{
LayoutInflater inflater=((Activity)context).getLayoutInflater();
row=inflater.inflate(layoutResourceId, parent,false);
holder=new PakistaniDrama();
holder.tvDramaName=(TextView)row.findViewById(R.id.dramaName);
holder.cbCheck=(CheckBox)row.findViewById(R.id.checkBox);
row.setTag(holder);
}
else
{
holder=(PakistaniDrama)row.getTag();
}
holder.tvDramaName.setText(dramaList.get(position).getDramaName());
holder.cbCheck.setChecked(checks.get(position));
return row;
}
logcat を見るとわかりますが、最初は、見える行すべてに対して convertview は null です。これは、最初はリサイクラーにビュー(つまりアイテム)がなかったためで、getView() は見えるアイテムごとに新しいビューを作成しますが、上にスクロールしてアイテム 1 が画面の外に出た瞬間に、それは Recycler に現在の状態(例えばTextView 'text'、私の場合はcheckboxがチェックされていれば、そのビューと関連付けてrecyclerに格納されます)で格納されます。
これで、上下にスクロールするとき、リストビューは新しいビューを作成するのではなく、リサイクラーにあるビューを使用するようになります。あなたの ログキャット で、'convertView' が null でないことに気がつくと思いますが、これは新しいアイテム 8 が convertview を使って描画されるからです。つまり、基本的にはアイテム 1 のビューをリサイクラーから取得して、代わりにアイテム 8 を展開するのですが、私のコードでそれを確認できます。もしあなたがチェックボックスを持っていて、位置0にそれをチェックした場合(item1にチェックボックスがあり、あなたがそれをチェックしたとします)、あなたがスクロールダウンするとき、アイテム8のチェックボックスがすでにチェックされているのが見えるでしょう、これはlistviewが同じビューを再使用し、パフォーマンスの最適化のために新しいものを作らない理由です。
重要なこと
1
. 決して
layout_height
と
layout_width
をリストビューの
wrap_content
として
getView()
を使用すると、リストビューに描画されるビューの高さを測定するための子プロセスをアダプタに取得させることになり、リストがスクロールされていないのに convertview を返すなど、予期せぬ振る舞いをする可能性があります。
<を使用します。
を使用するか、固定幅/高さを使用します。
2
. リストビューの後にレイアウトやビューを使いたい場合、リストビューの後に
match_parent
を
layout_height
リストビューの後のビューは画面の下に行くほど表示されないので、リストビューをレイアウトの中に置くとよいでしょう。
高さ
そして
幅
属性をレイアウトの幅に合わせます(例えば、レイアウトの幅が
320
で、高さが
280)
であれば、リストビューには同じ
高さ
と
幅
. これは、レンダリングされるビューの正確な高さと幅のgetView()を教えて、getView()が何度も何度もいくつかのランダムな行を呼び出すことはありませんし、スクロールする前でも変換ビューを返すなどの他の問題は発生しません、私は私のリストビューがlineaLayout内部にない限り、それはまたとしてビュー呼び出しと変換ビューを繰り返すなどの問題を抱えて、LinearLayout内部のリストビューを入れて私のための魔法のように働いていました(理由は分かりませんでした)これを自分でテストしている。
fill_parent
しかし、私は説明するのが得意ではありませんが、私のような他の初心者が私の経験の助けを得ることができると思ったので、私は今、人々が少し理解していることを望みます。 リストビュー フレームワークがどのように動作するか、それは本当に厄介でトリッキーなので、初心者はそれを理解するためにあまりにも多くの問題を発見したように
関連
-
[解決済み] TextViewでテキストを水平・垂直方向にセンタリングするには?
-
デフォルトのアクティビティが見つからない場合の対処法
-
を作ってください。*** makeするルールがない エラーの原因、分析、解決策
-
android block certificate validation CertPathValidatorException: 認証パスのトラストアンカーが見つかりません
-
Androidプロセス生存のためのソリューション
-
Androidの美しいSeekBarスタイルのカスタマイズ
-
[解決済み] android.os.NetworkOnMainThreadException' を修正するにはどうすればよいですか?
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] インスタンス状態の保存を使用してアクティビティ状態を保存するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
NetworkOnMainThreadException
-
java.lang.NullPointerException: NULLオブジェクト参照で仮想メソッド......を呼び出そうとしました。
-
アプリはGoogle検索でインデックスされません Androidmanifestのクソみたいな黄色い警告
-
Android開発で「Attempt to invoke virtual method 'XXX()' on null object reference」というヌルポインター例外に遭遇する。
-
アンドロイドスタジオのエラーを解決する --> Error:(1, 0) id 'com.android.application' を持つプラグインが見つかりません。
-
アプリケーションがメインスレッドで過剰に作業している可能性があります。
-
Android Nで報告されたエラーを解決する: android.os.FileUriExposedException: file:///storage/emulated/0/
-
Android ProgressBarのスタイルカラーを変更する
-
AndroidでListViewを使ってカスタムテーブルを描画する
-
android bluetooth--Bluetooth on、検索、ペアリング、接続