【问题标题】:NotifyDataSetChanged Recycler view : Cannot call this method while RecyclerNotifyDataSetChanged Recycler 视图:Recycler 时无法调用此方法
【发布时间】:2019-02-28 13:30:02
【问题描述】:

我正在制作一个聊天应用程序。我有一个回收者的观点。我使用 Picasso 下载用户和他正在聊天的朋友的图像。为了不为每条消息下载图像,当我下载第一张图像时,我只是将其放入位图中并每次都使用它。

问题:我无法调用 NotifyDataSetChanged。我已经尝试了我在网上找到的所有可能的东西。

ERROR : 
Cannot call this method while RecyclerView is computing a layout or scrolling android.support.v7.widget.RecyclerView

我必须“手动”刷新视图才能加载图像。文字没有问题。 它与 Handler 一起运行,但它甚至不进入函数(因此视图不会刷新)。 这是我的代码(除此 notifydatasetchanged 外,一切正常)

public class ChatActivity extends AppCompatActivity {

    private RecyclerView recyclerChat;

    private ListMessageAdapter adapter;

    private EditText editWriteMessage;
    private LinearLayoutManager linearLayoutManager;


    private FirebaseAuth mAuth;
    private DatabaseReference UserRef, MessageIDREF, UserMessageRef, SendMessageUser;

    private List<ChatClass> ListOfChats = new ArrayList<>();
    private ImageButton btnSend;
    private String  currentUserID, currentDateMessage, currentTimeMessage;

    private CommunActivit obj = new CommunActivit();
    private  String FRIENDID;
    private Toolbar mToolbar;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);



        mAuth=FirebaseAuth.getInstance();
        currentUserID = mAuth.getCurrentUser().getUid();

        MessageIDREF = FirebaseDatabase.getInstance().getReference().child("Friends");
        UserMessageRef = FirebaseDatabase.getInstance().getReference().child("Message").child(obj.getsIDMESSAGE());

        btnSend = (ImageButton) findViewById(R.id.btnSend);
        editWriteMessage = (EditText) findViewById(R.id.editWriteMessage) ;

        FRIENDID = obj.getsIDFRIEND();


        mToolbar = (Toolbar) findViewById(R.id.main_app_bar2);
        setSupportActionBar(mToolbar);
        ActionBar ab = getSupportActionBar();

        final String Title = obj.getsFRIENDName();
        ab.setTitle(Title);

        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                SendMessageToGroupChat();

                editWriteMessage.setText("");
            }
        });
        retrievedata();
/*recyclerChat = (RecyclerView)findViewById(R.id.recyclerChat);
adapter = new ListMessageAdapter(this,ListOfChats);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerChat.setLayoutManager(layoutManager);

recyclerChat.setItemAnimator(new DefaultItemAnimator());
recyclerChat.setAdapter(adapter);*/

        linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerChat = (RecyclerView) findViewById(R.id.recyclerChat);
        recyclerChat.setLayoutManager(linearLayoutManager);
        adapter = new ListMessageAdapter(this, ListOfChats);
        recyclerChat.setAdapter(adapter);

 /*  editWriteMessage.setOnTouchListener(new View.OnTouchListener() {
       @Override
       public boolean onTouch(View v, MotionEvent event) {

       recyclerChat.smoothScrollToPosition(adapter.getItemCount());

       return false;
   }
   });*/


    }


    private void SendMessageToGroupChat() {



        String message = editWriteMessage.getText().toString();
        String messageKey = UserMessageRef.push().getKey();

        if (TextUtils.isEmpty(message)) {
            Toast.makeText(this, "Please write a message first", Toast.LENGTH_SHORT).show();
        } else {
            Calendar calendarDate = Calendar.getInstance();
            SimpleDateFormat DateFormat = new SimpleDateFormat("MMM dd, yyyy");
            currentDateMessage = DateFormat.format(calendarDate.getTime());

            Calendar calendarTime = Calendar.getInstance();
            SimpleDateFormat TimeFormat = new SimpleDateFormat("hh:mm a");
            currentTimeMessage = TimeFormat.format(calendarTime.getTime());


            HashMap<String, Object> groupMessageKey = new HashMap<>();

            UserMessageRef.updateChildren(groupMessageKey);

            SendMessageUser = UserMessageRef.child(messageKey);

            HashMap<String, Object> messageInfoMap = new HashMap<>();

            messageInfoMap.put("name", obj.getsUsername());
            messageInfoMap.put("message", message);
            messageInfoMap.put("date", currentDateMessage);
            messageInfoMap.put("time", currentTimeMessage);
            messageInfoMap.put("image", obj.getsUserImageLink());

            SendMessageUser.updateChildren(messageInfoMap);
        }

    }

    public void retrievedata() {



        UserMessageRef.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) /**** HERE IS THE PROBLEM***/
            {

                if (dataSnapshot.exists()) {
                    DisplayMessages(dataSnapshot);
                }

            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
                if (dataSnapshot.exists()) {
                    DisplayMessages(dataSnapshot);
                }
            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }


    private void DisplayMessages(DataSnapshot dataSnapshot) 
    {
        Iterator iterator = dataSnapshot.getChildren().iterator();

while (iterator.hasNext()) {

    String chatDate = (String) ((DataSnapshot) iterator.next()).getValue();
    String chatImage = (String) ((DataSnapshot) iterator.next()).getValue();
    String chatMessage = (String) ((DataSnapshot) iterator.next()).getValue();
    String chatName = (String) ((DataSnapshot) iterator.next()).getValue();
    String chatTime = (String) ((DataSnapshot) iterator.next()).getValue();


    ListOfChats.add(new ChatClass(chatName, chatMessage, chatDate + "     " + chatTime, chatImage));


    adapter.notifyDataSetChanged();
    recyclerChat.smoothScrollToPosition(adapter.getItemCount()); /**AUTO SCROLL**/

}


}

class ListMessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private Context context;
    private ChatClass consersation;
    private List<ChatClass> List_of_chats;
    private CommunActivit obj = new CommunActivit();

    private Bitmap BitmapUser;
    private Bitmap BitmapFriend;

    public ListMessageAdapter(Context context, List<ChatClass> List_of_chats) {
        this.context = context;
        this.List_of_chats = List_of_chats;

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


        if (viewType == 1) {
            View view = LayoutInflater.from(context).inflate(R.layout.rc_item_message_friend, parent, false);
            return new ItemMessageFriendHolder(view);
        } else if (viewType == 2) {
            View view = LayoutInflater.from(context).inflate(R.layout.rc_item_message_user, parent, false);
            return new ItemMessageUserHolder(view);
        }
        return null;
    }

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



        final int pos =position;
        if (holder instanceof ItemMessageFriendHolder) {
            ((ItemMessageFriendHolder) holder).txtContent.setText(List_of_chats.get(position).getMessage());

            if (BitmapFriend == null) {


                Picasso.get().load(List_of_chats.get(position).getImageLink()).into(new Target() {


                    @Override
                    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                        BitmapFriend = bitmap;
                    }

                    @Override
                    public void onBitmapFailed(Exception e, Drawable errorDrawable) {

                    }

                    @Override
                    public void onPrepareLoad(Drawable placeHolderDrawable) {

                    }
                });
                ((ItemMessageFriendHolder) holder).avata.setImageBitmap(BitmapFriend);



            }
            else
            {

                ((ItemMessageFriendHolder) holder).avata.setImageBitmap(BitmapFriend);


                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        notifyDataSetChanged();
                    }
                });

            }
        }
        else
        {
            if (holder instanceof ItemMessageUserHolder) {
                ((ItemMessageUserHolder) holder).txtContent.setText(List_of_chats.get(position).getMessage());
                if (BitmapUser == null) {


                    Picasso.get().load(List_of_chats.get(position).getImageLink()).into(new Target() {


                        @Override
                        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                            BitmapUser = bitmap;
                        }

                        @Override
                        public void onBitmapFailed(Exception e, Drawable errorDrawable) {

                        }

                        @Override
                        public void onPrepareLoad(Drawable placeHolderDrawable) {

                        }
                    });
                    ((ItemMessageUserHolder) holder).avata.setImageBitmap(BitmapUser);
                } else {
                    ((ItemMessageUserHolder) holder).avata.setImageBitmap(BitmapUser);


                    new Handler().post(new Runnable() {
                        @Override
                        public void run() {
                            notifyDataSetChanged();
                        }
                    });


                }
            }
        }
    }

    @Override
    public int getItemViewType(int position) {
        int viewtype = -1;
        if (List_of_chats.get(position).getUsername().equals(obj.getsUsername())) {
            return 2;
        }
        else
            {
            return 1;
        }
    }

    @Override
    public int getItemCount() {
        return List_of_chats.size();
    }
}

class ItemMessageUserHolder extends RecyclerView.ViewHolder {


    public TextView txtContent;
    public CircleImageView avata;

    public ItemMessageUserHolder(View itemView) {
        super(itemView);
        txtContent = (TextView) itemView.findViewById(R.id.textContentUser);
        avata = (CircleImageView) itemView.findViewById(R.id.imageView2);
    }
}

class ItemMessageFriendHolder extends RecyclerView.ViewHolder {
    public TextView txtContent;
    public CircleImageView avata;

    public ItemMessageFriendHolder(View itemView) {
        super(itemView);
        txtContent = (TextView) itemView.findViewById(R.id.textContentFriend);
        avata = (CircleImageView) itemView.findViewById(R.id.imageView3);
    }
}

【问题讨论】:

    标签: android database android-recyclerview adapter notifydatasetchanged


    【解决方案1】:

    这是因为您在 onBindViewHolder 中调用 notifyDataSetChanged,如下所示:

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    
        ...
    
        ((ItemMessageFriendHolder) holder).avata.setImageBitmap(BitmapFriend);
    
    
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                notifyDataSetChanged();
            }
        });
    
       ...
    
    }
    

    您不应强制适配器在尚未完成绑定视图之前自行刷新。

    因此,您需要从您的onBindViewHolder 中删除以下代码:

    new Handler().post(new Runnable() {
        @Override
        public void run() {
            notifyDataSetChanged();
        }
    });
    

    然后在需要时致电notifyDataSetChanged()。例如,当您的数据集发生更改时。

    【讨论】:

    • 你好,我已经使用了:adapter.notifyDataSetChanged();如果 displaymessage() 方法 => 视图已更新,但问题是视图内的图像未更新,所以我看到的只是文本。如果在屏幕上移动我的手指,所有图像都会立即出现在视图中......
    • 图像正在加载,因为您总是检查前一个位图是否为空。只需将((ItemMessageFriendHolder) holder).avata.setImageBitmap(BitmapFriend); 移动到您的public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
    • 但是如果我这样做,在每一条新消息都会下载图像,但我想要的是图像被下载一次,然后存储到 BitmapFriend 中,这样我就可以使用它而不是下载再上图
    • 但是你是对的,因为我每次都检查位图是否为空而不是我使用布尔值,它可以工作谢谢
    【解决方案2】:

    试试这个。

    dialeecyclerView.post(new Runnable()
                    {
                        @Override
                        public void run() {
                        myadapter.notifyDataSetChanged();
                    }
                    });
    

    来源 - Cannot call this method while RecyclerView is computing a layout or scrolling when try remove item from recyclerview

    【讨论】:

    • 我试过了,但屏幕上仍然没有加载图像
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多