2016-09-23 3 views
5

タッチフリーデバイスにRecyclerViewグリッドのリストセレクタを実装しようとしています。私の実装は正常に動作しますが、効率的なパフォーマンスが得られないnotifyItemChanged()メソッドが必要です。私はアイテムの100sのグリッドを持っているので、もし私が高速にスクロールすると(キーボードとスクロールしてonKey)、グリッドはたくさんのアイテムが更新されてゆきます。これを避ける方法はありますか?タッチフリーデバイスのRecyclerViewのListSelector(onKeyリスナーを使用)

活動

mRecyclerView.setOnKeyListener(new View.OnKeyListener() { 
     @Override 
     public boolean onKey(View v, int keyCode, KeyEvent event) { 
      RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager(); 

      if (event.getAction() == KeyEvent.ACTION_DOWN) { 
       switch (keyCode) { 
        case Constants.KEYCODE_UP: 
         return moveSelection(lm, -1, true); 

        case Constants.KEYCODE_DOWN: 
         return moveSelection(lm, 1, true); 
       } 
      } 
      return false; 
     } 
}); 

public boolean moveSelection(RecyclerView.LayoutManager lm, int direction, boolean verticalMovement) { 
    ... 
    //just calculate the position to move to and pass it to selectedPosition 
    return mAdapter.tryMoveSelection(lm, selectedPosition); 
} 

アダプタ

@Override 
    public void onBindViewHolder(ViewHolder holder, int position) { 
     // - get element from your dataset at this position 
     // - replace the contents of the view with that element 
     mViewHolder = holder; 

     holder.itemView.setSelected(mFocusedItem == position); 
     ... 
    } 

public boolean tryMoveSelection(RecyclerView.LayoutManager lm, int selectedPosition) { 
     notifyItemChanged(mFocusedItem); 
     mFocusedItem = selectedPosition; 
     notifyItemChanged(mFocusedItem); 
     lm.scrollToPosition(mFocusedItem); 
     return true; 
    } 

答えて

1

私はすべてnotifyItemChanged()を伴わないより良い解決策を見つけました。

  • clearSelection(int position)
  • setSelection(int position)

と、次のようにtryMoveSelectionにそれらを呼び出す:

boolean tryMoveSelection (RecyclerView.LayoutManager lm, int selectedPosition) { 
    myRecyclerView.clearSelection(selectedPosition); 
    mFocusedItem = selectedPosition; 
    myRecyclerView.setSelection(mFocusedItem); 
    lm.scrollToPosition(mFocusedItem); 
    mRecyclerView.requestFocus(); 
    return true; 
} 

詳細を次のように私は何をしてRecyclerViewクラスを拡張し、2つの新しいメソッドを作成します:

public void setSelection(int position) { 
    ViewHolder viewHolder = this.findViewHolderForAdapterPosition(position); 
    if (this.getChildCount() > 0 && viewHolder != null) { 
     viewHolder.itemView.setSelected(true); 
     viewHolder.itemView.requestFocus(); 
    } 
} 

public void clearSelection(int position) { 
    ViewHolder viewHolder = this.findViewHolderForAdapterPosition(position); 
    if (viewHolder != null) { 
     viewHolder.itemView.setSelected(false); 
     viewHolder.itemView.clearFocus(); 
     viewHolder.itemView.setBackgroundResource(0); 
    } 
} 
1

あなたのコードに追加することができます最適化のいくつかあります。

  1. notifyItemChanged() WHを呼び出さないでくださいen RecyclerViewがスクロールしています。そのための便利な方法がいくつかあります:

  2. getScrollState()が、その後SCROLL_STATE_IDLEnotifyItemChanged()を呼んでいます。

  3. アダプタも便利な方法のカップルが上書きすることがあります。

0

「​​」と呼ぶときは、「ペイロード」を使用する必要があります。ペイロードは、これらの場合にのみ設計されました。部分的な更新を行い、完全なバインドを実行する必要がない場合。

@Override 
public void onBindViewHolder(VH holder, int position, List<Object> payloads) { 
    if (payloads.isEmpty()) { 
     // Do a full bind 
    } else if (payloads.contains("focusedItemChange")) { 
     holder.itemView.setSelected(isFocusedPositon(position)); 
    } 
} 
:その後、あなたのアダプタでこのような何かを、 notifyItemChanged(1, "focusedItemChange")

したがって、たとえば、あなたがあなたのアダプタに通知することができます

関連する問題