【问题标题】:Add item to RecyclerView dynamically将项目动态添加到 RecyclerView
【发布时间】:2017-01-22 00:54:30
【问题描述】:

我希望能够动态地将项目添加到我的 ReclycerView。

当一个项目加载时 -> setText() -> 我在列表中添加另一个项目。

@Override
public void onBindViewHolder(ViewHolder holder, final int position) {
    final Message message = mDataset.get(position);

    if(message.isAnswers()) {
        holder.mAnswer1Button.setText(message.getAnswer1());
        holder.mAnswer2Button.setText(message.getAnswer2());

        holder.mAnswer1Button.setOnClickListener(v -> {
            if(message.getChild1() > 0) {
                add(position + 1, dataListShared.get(message.getChild1()));
                holder.mAnswer1Button.setClickable(false);
                holder.mAnswer2Button.setEnabled(false);
            }
        });
    } else {
        holder.mMessageTextView.setText(message.getMessage());
            if(message.getChild1() > 0) {
                add(position + 1, dataListShared.get(message.getChild1()));
                holder.mMessageTextView.setEnabled(false);
            }
    }
}

这就是我在onBindViewHolder 里面的东西。当我在第一个案例if() 上单击按钮时,该项目被添加到列表中。在第二个案例else() 上,我希望在当前项目上设置文本,而不是添加另一个。

我怎样才能做到这一点?

此外,为什么add() 在 onClickListener 内部起作用,而不在它外部起作用?

我得到的错误是:

java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling

谢谢! :)

【问题讨论】:

  • onClickListener 会在很久以后执行,当 View 实际显示并点击时,而 onBindViewHolder() 中的 add() 会在绑定视图时立即调用。
  • 另外,还有一个稍后我会尝试的回调,onViewAttachedToWindow()。也许在那里添加代码会有所帮助(我还没有实际测试过)。
  • 谢谢大佬,我试试
  • 你到底想达到什么目标?
  • 我想添加项目(如果布局只有一个 textView 而没有按钮)-> 添加另一个项目(如果布局没有按钮)-> 添加另一个...直到我们得到到将有一个按钮的项目

标签: android android-recyclerview


【解决方案1】:

错误本身是不言自明的......在onBindViewHolder 中对setOnClickListener 很危险。此方法是刷新每个回收站项目的步骤。

您应该将方法 setOnClickListener 移动到适配器上的内部类 ViewHolder

class MyViewHolder extends RecyclerView.ViewHolder
    {
        private final OnClickListener mOnClickListener = new MyOnClickListener();
        Button mAnswer1Button, mAnswer2Button;
        public MyViewHolder (View itemView) {
            super(itemView);
            mAnswer1Button = (Button) itemView.findViewById(R.id.item);
            mAnswer2Button = (Button) itemView.findViewById(R.id.item);
            mAnswer1Button.setOnClickListener(mOnClickListener);

        }


       @Override
       public void onClick(final View view) {
            //Now your Logic ....
       }
    }

您可以做的另一件事是设置创建接口OnItemClickListener 并声明onItemClick,然后在您为特定回收站视图实现OnItemClickListener 设置适配器的位置进行活动,您可以在此处动态添加另一个项目并再次setAdapternotifyDataSetChanged()

您的界面

 public interface OnItemClickListener{
      public void onItemClick(int position);
 }

你的 MainActivity

   class MainActivity implements OnItemClickListener{
       RecyclerView mRecyclerView ;

       @Override
    public void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.layout);
    mRecyclerView = (RecyclerView ) findViewById(R.id.recyclerview);
    mAdapter= new MyAdapter(ArrayList, getContext(), MainActivity.this);

    }

       @Overrride
       public void onItemClick(int position)
       {
               //Now your Logic ....

       } 
   } 

现在您可以通过在ViewHolder 类中设置onClickListener mAnswer1Button 并在onClick 中调用此方法,从Adpater 类调用此方法onItemClick

【讨论】:

    【解决方案2】:

    正如评论,我认为它应该像这样工作:

    private int position;
    
    @Override
    public void onBindViewHolder(ViewHolder holder, final int position) {
        this.position = position;
    }
    
    
    @Override
    public void onViewAttachedToWindow(ViewHolder holder) {
        final Message message = mDataset.get(position);
    
        if(message.isAnswers()) {
            holder.mAnswer1Button.setText(message.getAnswer1());
            holder.mAnswer2Button.setText(message.getAnswer2());
    
            holder.mAnswer1Button.setOnClickListener(v -> {
                if(message.getChild1() > 0) {
                    add(position + 1, dataListShared.get(message.getChild1()));
                    holder.mAnswer1Button.setClickable(false);
                    holder.mAnswer2Button.setEnabled(false);
                }
            });
        } else {
            holder.mMessageTextView.setText(message.getMessage());
                if(message.getChild1() > 0) {
                    add(position + 1, dataListShared.get(message.getChild1()));
                    holder.mMessageTextView.setEnabled(false);
                }
        }
    }
    

    在 onBindViewHolder() 中,您显然无法更改数据集 - 我猜是因为框架仍在忙于显示先前的数据集。但是当将位置保存在实例变量中并在 onViewAttachedToWindow() 中更新数据集时,RecylerView 应该准备好接收更多数据。

    但老实说,我不会将所有这些逻辑添加到 ViewHolder,而是将一个接口传递给它,以便将逻辑保存在更中心的位置,例如演示者。

    【讨论】:

    • onBindViewHolder() 也不行,我试试主播?从来没有听说过...我现在就用谷歌搜索。谢谢:)
    • 哦,这令人困惑,抱歉。使用演示者不会帮助您解决这个问题,它只是一个架构建议。将逻辑移动到 onViewAttachedToWindow() 时是否遇到相同的异常?
    • 是的,同样的例外......我认为 RecyclerView 还没有准备好
    • 耻辱。我仍然不能自己尝试,但也许@pskink 建议依赖 Recyclerview#isComputingLayout() 可能会奏效。有关示例,请参见 stackoverflow.com/a/36913261/1430422
    • Idk 我要在哪里添加isCOmputingLayout()?我需要一个监听器来说明项目何时完成加载。或者像一个线程每秒运行一次,直到它到达true?这对我来说似乎不是一个好的解决方案。如果我可以在每次添加 Item 时都有一个监听器,那将是完美的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2011-11-15
    • 2012-08-27
    • 1970-01-01
    相关资源
    最近更新 更多