2016-05-02 15 views
4

問題を解決するためのコードを示します。RecyclerView.Adapter onBindViewHolder()が間違った位置になる

私はカスタムオブジェクトからデータセットを取りタブ付きフラグメント内部recyclerviewを持っている:

@Override 
public void onBindViewHolder(final ViewHolder holder, final int position) { 

    ItemMes item = mListaItens.get((position)); 

    holder.descricao.setText(item.getDescrição()); 
    holder.valor.setText(MainActivity.decimalFormatWithCod.format(item.getValor())); 

    ... 

    holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { 
     @Override 
     public boolean onLongClick(View v) { 

      new MaterialDialog.Builder(mContext) 
        .title(holder.descricao.getText().toString()) 
        .items(R.array.opcoes_longclick_item) 
        .itemsCallbackSingleChoice(-1, new MaterialDialog.ListCallbackSingleChoice() { 
         @Override 
         public boolean onSelection(MaterialDialog dialog, View view, int which, CharSequence text) { 

          switch (which) { 
           case 0: 
            mParentFragment.showUpdateItemDialog(position); 
            return true; 

           case 1: 
            mParentFragment.showDeleteItemDialog(position); 
            return true; 
          } 

          return false; 
         } 
        }) 
        .show(); 

      return true; 
     } 
    }); 

} 
:私は、アダプタのonBindViewHolder()でリスト項目のlongclick動作を設定
mRecyclerView = (RecyclerView) v.findViewById(R.id.recyclerview); 

mRecyclerView.setLayoutManager(mLayoutManager); 

mRecyclerAdapter = new MyRecyclerAdapter(mMes.getListaItens(), this, getActivity()); 

mRecyclerView.setAdapter(mRecyclerAdapter); 

その後

、アイテム自体を削除するの世話をするフラグメントのメソッド:

public void showDeleteItemDialog(int position) { 

    final ItemMes item = mMes.getListaItens().get(position); 

    new MaterialDialog.Builder(getActivity()) 
      .title("Confirmar Remoção") 
      .content("Tem certeza que deseja remover " + item.getDescrição() + "?") 
      .positiveText("Sim") 
      .negativeText("Cancelar") 
      .onPositive(new MaterialDialog.SingleButtonCallback() { 
       @Override 
       public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { 
        deleteItem(item); 
       } 
      }) 
      .show(); 

} 

public void deleteItem(ItemMes item) { 

    getMainActivity().deleteItemFromDatabase(item.getID()); 

    int position = mMes.getListaItens().indexOf(item); 

    mMes.getListaItens().remove(position); 

    mRecyclerAdapter.notifyItemRemoved(position); 

    atualizaFragment(); 

} 

そして、DB操作を行う活動で、最終的方法:

public int deleteItemFromDatabase(long id) { 

    SQLiteDatabase db = dataBaseHelper.getWritableDatabase(); 

    String where = DBHelper.COLUNA_ID + " = ?"; 

    String[] args = {String.valueOf(id)}; 

    int rowsAffected = db.delete(DBHelper.TABELA_ITEM, where, args); 

    db.close(); 

    return rowsAffected; 

} 

今私は手順を再現します: 私はリストビューで3 itensを示しています。それから私は削除しようと最初:

1 - longclickは正しいインデックスを渡し傍受された: enter image description here

2 - アイテムが正しくデータベースから削除されます。 enter image description here

3 - 結局のところこれは、予想通り、アダプターは、私はこの2項目リストの最初の項目を削除しようとする場合、私は間違ってPOSIを取得し、SO 2つの項目... enter image description here

を格納して表示されますションは(0である必要があり、ある1): The position = 1

そして私は私が間違っている位置を取得し、この2項目リストの最後の項目を削除しようとした場合も、(1であるべきであり、2): enter image description here

質問:サイズ2のデータセットがあり、アダプターがそれを知っている場合、どのようにしてをBindViewHolder(ViewHolderホルダー、int [最後のインデックス+1])と呼びますかenter image description here

何が間違っているかわかりません。だから私は助けを求めます。私はこのプロジェクトをあきらめることを考えています。なぜなら、私はすべてのことを正しくやっていますが、いつも何かが動かず、疲れました。 ありがとうございます。

+0

アダプタコードも含める必要があります。これは、アダプタが「削除」を正しく処理していないために起こりそうです。その総数を減らす必要があります。 IDが位置である単純なリストを使用している場合は、ビューを再作成する必要がある問題が発生します。 –

+0

完全なコードを見ることなく、確かに言うのは難しいです。 –

+0

あなたが欲しい部分を教えて、私が投稿したら、すべてが悪くなるでしょう。たぶん私はbitbucketにいくつかのファイルのURLを貼り付けることができます... – Informatheus

答えて

2

コメントに記載されているアダプタコードを見てみるとかなり簡単です。これを試してください:notifyItemRemoved()に電話するのではなく、notifyDataSetChanged()に電話してください。これは、アダプタがデータセットの再バインドを行い(そしてViewHoldersを再作成するため)、かなり高価ですが、要素を削除する場合はArrayListを使用しているため、実際には最も簡単な方法です。そうしないと、アイテムの位置を追跡する必要があり、アイテムが削除されると、他のアイテムの位置を変更することはできません。また、アイテムがデータセット内の位置を移動するケースを処理することもできません。

+0

私は同様の問題が発生している可能性があります:http://stackoverflow.com/questions/43531900/android-how-to-fix-recyclerview-onbindviewholder私はどのように修正するかに関する考えやアイデアを感謝します。 – AJW

5

私は、onBindViewHolder(VHホルダー、int位置)の位置が間違っている間に、holder.getAdapterPosition()が常に正しい位置を取得していることに気付きました。

だから私はから私のコードを変更:へ

ItemMes item = mListaItens.get((position)); 

... 

mParentFragment.showUpdateItemDialog(position); 

... 

mParentFragment.showDeleteItemDialog(position); 

.... 

ItemMes item = mListaItens.get((holder.getAdapterPosition())); 

... 

mParentFragment.showUpdateItemDialog(holder.getAdapterPosition()); 

... 

mParentFragment.showDeleteItemDialog(holder.getAdapterPosition()); 

.... 

、すべてがうまく動作します。これは非常に奇妙ですが... ありがとうございました。

0

int adapterPos=holder.getAdapterPosition(); 
     if (adapterPos<0){ 
      adapterPos*=-1; 
     } 

ItemMes item = mListaItens.get((adapterPos)); 
mParentFragment.showUpdateItemDialog(adapterPos); 

使用adapterPos代わりの位置変数)(onBindViewHolderにこのコードを試してみてください。

関連する問題