Mi aplicación se bloquea con addAll (int index, Colección c) en la versión anterior de Android (No porque sublista)

votos
0

Estoy tratando de añadir nuevos elementos a una vista de lista throug el método addAll y puedo hacerlo en la última versión de Android, pero cuando trato en las versiones anteriores de que se estrelle.

¿Puede alguien ayudarme a entender por qué y cómo solucionarlo.

Función donde me sale el error

public void appendMessages(List<Message> moreMessages){
        this.messages.addAll(0,moreMessages);
    }

Tengo que añadir que en la parte superior de la lista.

Error

09-19 13:12:59.437 12909-12909/com.example.rjrod.legendchat E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.rjrod.legendchat, PID: 12909
    java.util.ConcurrentModificationException
        at java.util.AbstractList$SubAbstractList.size(AbstractList.java:360)
        at java.util.AbstractList$SubAbstractList.addAll(AbstractList.java:265)
        at com.example.rjrod.legendchat.adapter.MensagemAdapter.appendMessages(MensagemAdapter.java:136)
        at com.example.rjrod.legendchat.MainActivity$2.onScroll(MainActivity.java:169)
        at android.widget.AbsListView.invokeOnItemScrollListener(AbsListView.java:1461)
        at android.widget.AbsListView.trackMotionScroll(AbsListView.java:4987)
        at android.widget.AbsListView.scrollIfNeeded(AbsListView.java:3398)
        at android.widget.AbsListView.onTouchMove(AbsListView.java:3774)
        at android.widget.AbsListView.onTouchEvent(AbsListView.java:3612)
...

Cuando lo llamo

listMensages.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                Log.d(TAG, onScroll:  + view.getFirstVisiblePosition() +   + listMensages.getCount() +  + (19*(k)-visibleItemCount) +  + k+  +numberLists);


                if(view.getFirstVisiblePosition() == 0 && listMensages.getCount()>=19*(k)-visibleItemCount && k<numberLists && k>=1 && k!=z){

                    Log.d(TAG, ENTREI:  + z +   + k);


                        adapter.appendMessages(messagesList.subList(messagesList.size()-20*(k+1),messagesList.size()-21-((k-1)*20)));
                        adapter.notifyDataSetChanged();
                        listMensages.smoothScrollToPosition(19);
                        z=k;
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            k++;
                        }
                    }, 100);


                        //loaded=true;
                    }
                    if(view.getFirstVisiblePosition() == 0 && listMensages.getCount()>=19-visibleItemCount && k==numberLists){
                        Log.d(TAG, ENTREI 2: );

                        adapter.appendMessages(messagesList.subList(messagesList.indexOf(messagesList.get(0)),messagesList.size()-21-((k-1)*20)));
                        adapter.notifyDataSetChanged();
                        listMensages.smoothScrollToPosition(19);
                        k++;
                    }
                    if(k==0){
                        k=1;
                    }



            }
        });

Si se necesita otra cosa sólo dime y lo añadiré. (Necesito que esto funcione de al menos 21 SDK)

Gracias

Adaptador

public class MensagemAdapter extends ArrayAdapter<Message> {

    private Context context;
    private List<Message> messages;
    private List<Users> users;
    private static final String TAG = MensagemAdapter;


    public MensagemAdapter(@NonNull Context context, @NonNull List<Message> objects, @NonNull List<Users> users) {
        super(context, 0, objects);
        this.context=context;
        this.messages = objects;
        this.users = users;
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        View view = null;
        //Log.d(TAG, getView:  + position);


            if (messages != null) {

                LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
                Message message = messages.get(position);
                //Log.d(Num, getView:  + message.getUserId() +   + message.getId());
                if (message.getUserId() == 1) {
                    assert inflater != null;
                    view = inflater.inflate(R.layout.right_no_attach, parent, false);
                    TextView textoMensagem = view.findViewById(R.id.tv_mensage);
                    textoMensagem.setText(message.getContent());
                    if (message.getAttachments() != null) {

                        for (int i = 0; i < message.getAttachments().size(); i++) {
                            //view = inflater.inflate(R.layout.right_attach,parent,false);
                            if (i == 0) {
                                ImageView attach = view.findViewById(R.id.imageView1);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);

                            } else if (i == 1) {
                                ImageView attach = view.findViewById(R.id.imageView2);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);
                            } else if (i == 2) {
                                ImageView attach = view.findViewById(R.id.imageView3);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);
                            } else {
                                ImageView attach = view.findViewById(R.id.imageView3);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);
                            }

                        }
                    }

                } else {
                    assert inflater != null;
                    view = inflater.inflate(R.layout.left_no_attach, parent, false);
                    TextView nomeMensagem = view.findViewById(R.id.nomeId);
                    nomeMensagem.setText(users.get(message.getUserId() - 1).getName());
                    ImageView avatar = view.findViewById(R.id.avatarIm);
                    Picasso.get().load(users.get(message.getUserId() - 1).getAvatarId()).transform(new CircleTransform()).into(avatar);
                    TextView textoMensagem = view.findViewById(R.id.tv_mensage);
                    textoMensagem.setText(message.getContent());
                    if (message.getAttachments() != null) {

                        for (int i = 0; i < message.getAttachments().size(); i++) {
                            //view = inflater.inflate(R.layout.right_attach,parent,false);
                            if (i == 0) {
                                ImageView attach = view.findViewById(R.id.imageViewA);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);

                            } else if (i == 1) {
                                ImageView attach = view.findViewById(R.id.imageViewB);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);
                            } else if (i == 2) {
                                ImageView attach = view.findViewById(R.id.imageViewC);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);
                            } else {
                                ImageView attach = view.findViewById(R.id.imageViewD);
                                attach.setVisibility(View.VISIBLE);
                                Picasso.get().load(message.getAttachments().get(i).getThumbnailUrl()).into(attach);
                            }

                        }
                    }

                }


                if (message.getAttachments() == null) {
                    TextView textoMensagem = view.findViewById(R.id.tv_mensage);

                    textoMensagem.setText(message.getContent());
                }



        }
        return view;
        }


    public void appendMessages(List<Message> moreMessages){
        Log.d(TAG, appendMessages:  + this.messages +   + moreMessages);
        this.messages.addAll(moreMessages);

    }


    }
Publicado el 19/09/2018 a las 13:21
fuente por usuario
En otros idiomas...                            


2 respuestas

votos
0

El problema es que estamos tratando de modificar la lista, mientras que la lista ya está siendo modificado en otro lugar, por lo que se obtiene ConcurrentModificationException.

Tratar de restringir la lista de modificaciones en un solo hilo, por ejemplo, la interfaz de usuario. A partir de su código publicado Asumo la concurrencia se produce en onScollun método que es llamada repetidamente mientras que su modificación de la lista aún no está terminado. Aquí está un ejemplo sencillo de mover su adapter.appendMessages()función a la cola de hilo de interfaz de usuario:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        adapter.appendMessages(messagesList.subList(messagesList.indexOf(messagesList.get(0)),messagesList.size()-21-((k-1)*20)));
        adapter.notifyDataSetChanged();
        listMensages.smoothScrollToPosition(19);
        ...
    }
});
Respondida el 19/09/2018 a las 15:27
fuente por usuario

votos
0

Para arreglar un problema gira simplemente cambiar el constructor del adaptador.

public MensagemAdapter(@NonNull Context context, @NonNull List<Message> objects, @NonNull List<Users> users) {
        super(context, 0,  new ArrayList<>(objects));
        this.context=context;
        this.messages =   new ArrayList<>(objects);
        this.users = users;
    }
Respondida el 19/09/2018 a las 14:46
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more