1. ホーム
  2. android

[解決済み] RecyclerView.ViewHolder - getLayoutPosition と getAdapterPosition の比較。

2023-02-14 11:49:19

質問

新しいサポートライブラリのバージョン(22.x)からは getPosition() メソッドの RecyclerView.ViewHolder クラスのメソッドが非推奨となり、このトピックで紹介されているメソッドに取って代わられました。ドキュメントを読んでも違いがよくわかりません。 どなたか平易な言葉で違いを説明していただけませんか?

私は次のような使用例を持っています。アダプタに List を与え、さらに各リストアイテムに追加情報を関連付けたいと考えています。位置と余分のマッピングがあり、そのマッピングはホルダーが自分の位置の余分を取得し、それを使って何かできるようにするためです。ホルダーでは、どのメソッドを使用する必要がありますか?

インデックス0と1のリストアイテムが入れ替わったとき、ホルダーの位置はどうなるのでしょうか?メソッドは何を返すのですか?

どのように解決するのですか?

これは厄介な状況で、ドキュメントが十分でないのが残念です。

アダプタのコンテンツが変更されたとき (そして notify***() ) RecyclerViewは新しいレイアウトを要求します。その瞬間から、レイアウトシステムが新しいレイアウトを計算することを決定するまで( <16 ms )、レイアウトはまだアダプタの変更を反映していないため、レイアウト位置とアダプタ位置が一致しないことがあります。

あなたの使用例では、データがアダプタの内容に関連しているため(そしてアダプタの変更と同時にデータも変更されると仮定します)、あなたは adapterPosition .

しかし、もしあなたが notifyDataSetChanged() を呼び出すと、すべてが無効になってしまうため、RecyclerViewは次のレイアウトが計算されるまでViewHolderのアダプタの位置を知ることができません。その場合 getAdapterPosition()RecyclerView#NO_POSITION ( -1 ).

しかし、もしあなたが notifyItemInserted(0) を呼び出した場合、その getAdapterPosition() の位置にあった ViewHolder の 0 を返すようになります。 1 をすぐに返し始めます。つまり、粒状の通知イベントをディスパッチしている限り、常に良い状態(新しいレイアウトがまだ計算されていなくても、アダプタの位置がわかる)であることがわかります。

別の例として、ユーザがクリックしたときに何かをする場合、もし getAdapterPosition() が返す NO_POSITION を返す場合、ユーザーが何をクリックしたのかわからないので、そのクリックを無視するのが最善です(例えば、項目を調べるための安定したIDなど、他のメカニズムがない限り)。

レイアウト位置が良いときのために編集する

例えば LinearLayoutManager を使用していて、現在クリックされているアイテムの上の ViewHolder にアクセスしたいとします。その場合、レイアウトポジションを使用して、上のアイテムを取得する必要があります。

mRecyclerView.findViewHolderForLayoutPosition(myViewHolder.getLayoutPosition() - 1)

ユーザーが現在画面上で見ているものと一致するため、レイアウト位置を使用する必要があります。