2017-01-22 8 views
1

ReclycerViewにアイテムを動的に追加できます。RecyclerViewにアイテムを動的に追加する

アイテムがロードするとき - > 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()にいるとき、ボタンをクリックすると、アイテムがリストに追加されます。 2番目のケースelse()では、この現在のアイテムにテキストを設定し、既に別のアイテムを追加したいと思います。

どうすればこの問題を解決できますか?

さらに、add()はなぜonClickListenerの内部で動作しますが、その外側では動作しないのですか?

私が手にエラーがある:

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

ありがとう! :)

+0

ViewHolderクラスでonClickListener mAnswer1Buttonを設定して、このメソッドを呼び出すことにより、Adpater CLASからこのメソッドonItemClickを呼び出すことができますonBindViewHolder()内のadd()はビューをバインドするときにただちに呼び出されます。 – Micha

+0

また、後で私が試みるコールバック、onViewAttachedToWindow()があります。たぶんそこにコードを追加すると(私は実際にこれをテストしていない)。 – Micha

+0

ありがとう、私はそれを試してみます –

答えて

0

これは糸問題のためだと思います。ほとんどのオペレーティングシステムにはスレッド機構があります。スレッドの件名は、オペレーティングシステムの上位トピックです。

ここにスレッドが2つあります。 add機能

setOnClickListener

    1. 単純にスレッドを使用すると、最終的としての機能を定義する場合、あなたはあなたの問題を解決する互いの変数、関数などにアクセスすることはできません。

      あなたの追加機能はfinalと定義する必要があると思います。コメントとしては例えば、

      final void add(... 
      
  • +0

    ええ、そうではありません。おそらく、別のスレッドで実行するよりも優れた解決策があります。ありがとうtho –

    +0

    ''ここには2つのスレッドがあります。 ''、いいえ、ここにスレッドが1つしかありません。 – pskink

    +0

    @pskink解決方法は何ですか? –

    0

    は、私はそれがこのように動作するはずだと思う:

    onBindViewHolder()、あなたは明らかにデータセットを変更することはできませんで
    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); 
          } 
        } 
    } 
    

    - フレームワークは、まだ表示ビジー状態であると私は推測します前のデータセット。しかし、インスタンス変数に位置を保存し、onViewAttachedToWindow()でデータセットを更新する場合、RecylerViewはより多くのデータを準備する必要があります。

    正直言って、このロジックをViewHolderにすべて追加するのではなく、インターフェイスを渡して、ロジックをプレゼンターのようにもっと中央に置くことができます。

    +0

    'onBindViewHolder()'もうまくいきません、私はプレゼンターに挑戦しますか?それを聞いたことがない...私は今それをgoogleします。ありがとう:) –

    +0

    ああ、それは混乱していた、申し訳ありません。プレゼンターを使用してもこの問題を解決するのに役立つわけではなく、単なる建築上の提案です。ロジックをonViewAttachedToWindow()に移動するときに同じ例外がありますか? – Micha

    +0

    イエス、同じ例外...私はRecyclerViewがまだ準備ができていないと思います –

    1

    エラー自体は自明です... setOnClickListenerにはonBindViewHolderで危険です。このメソッドは、各リサイクル項目をリフレッシュするステップです。

    アダプタの内部クラスであるsetOnClickListenerViewHolderに移動する必要があります。

    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を宣言してから、あなたが動的にあそこことができ、この特定のリサイクルビューimplment OnItemClickListener用のアダプタを設定しているところから活動を行うれます再び別の項目とsetAdapterを追加したり、notifyDataSetChanged()

    あなたのインターフェース

    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 .... 
    
         } 
        } 
    

    今、あなたはonClickListenerはかなり後に実行され、時に表示onClick

    関連する問題