2016-05-02 310 views
4

我将显示代码并执行解决问题的步骤。RecyclerView.Adapter onBindViewHolder()获取错误的位置

我有一个标签片段,是以数据集从一个自定义对象内recyclerview:

mRecyclerView = (RecyclerView) v.findViewById(R.id.recyclerview); 

mRecyclerView.setLayoutManager(mLayoutManager); 

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

mRecyclerView.setAdapter(mRecyclerAdapter); 

我设置列表项的longclick行为适配器的onBindViewHolder():

@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; 
     } 
    }); 

} 

然后,在片段照顾的方法删除的项目本身:

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(); 

} 

最后在的活动,做数据库操作的方法:

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; 

} 

现在我要重现步骤: 我展示在ListView 3个itens。然后我尝试删除第一:

1 - 该longclick被拦截传递正确的指标: enter image description here

2 - 该项被正确地从数据库中删除: enter image description here

3 - 毕竟这一点,正如所料,适配器存储和显示2项... enter image description here

所以,如果我尝试删除此2项列表的第一个项目,我得到了错误的POSI重刑(应该是0,1): The position = 1

并且如果我尝试删除此2项列表,我得到了错误的位置的最后一个项目(应为1,是2): enter image description here如果我有一个大小为2(和适配器知道它)的数据集,它如何可以调用onBindViewHolder(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

我注意到,在positionBindViewHolder(VH holder,int position)方法错误时,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

尝试在onBindViewHolder()此代码

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

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

使用adapterPos代替的位置可变。