gpt4 book ai didi

android - 在 RecyclerView 中配置 ItemTouchHelper 以处理被显示的另一个 Snackbar 关闭的 Snackbar

转载 作者:行者123 更新时间:2023-12-05 00:04:19 25 4
gpt4 key购买 nike

我的应用程序中有一个包含消息的 RecyclerView。在向右滑动时,我将其配置为删除消息,在向左滑动时,我将其配置为存档消息。下面是 ItemTouchHelper 部分删除归档相关的代码:

if (direction == ItemTouchHelper.LEFT) {
donorMessagesAdapter.deleteMessages(position);
} else if (direction == ItemTouchHelper.RIGHT) {
donorMessagesAdapter.archiveMessages(position);
}

下面是 deleteMessages() 和 archiveMessages() 函数(它们几乎相同):

public void deleteMessages(final int position) {
recentlyDeletedPeer = sortedPeers.get(position);
recentlyDeletedPeerPosition = position;

sortedPeers.remove(position);
notifyItemRemoved(position);

Snackbar snackbar = Snackbar.make(activity.findViewById(R.id.constraint_layout),
"Messages Deleted", Snackbar.LENGTH_LONG);
snackbar.setAction("UNDO", new View.OnClickListener() {
@Override
public void onClick(View view) {
sortedPeers.add(recentlyDeletedPeerPosition, recentlyDeletedPeer);
notifyItemInserted(recentlyDeletedPeerPosition);
}
});
snackbar.setActionTextColor(0xff0099ff);

snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT || event == Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE) {
MainActivity.database.receivedMessagesDao().deleteAllReceivedMessagesFromSender(email, recentlyDeletedPeer);
MainActivity.database.sentMessagesDao().deleteAllSentMessagesFromReceiver(email, recentlyDeletedPeer);
}
}
});

snackbar.show();
}

public void archiveMessages(final int position) {
recentlyArchivedPeer = sortedPeers.get(position);
recentlyArchivedPeerPosition = position;

sortedPeers.remove(position);
notifyItemRemoved(position);

Snackbar snackbar = Snackbar.make(activity.findViewById(R.id.constraint_layout),
"Messages archived", Snackbar.LENGTH_LONG);
snackbar.setAction("UNDO", new View.OnClickListener() {
@Override
public void onClick(View view) {
sortedPeers.add(recentlyArchivedPeerPosition, recentlyArchivedPeer);
notifyItemInserted(recentlyArchivedPeerPosition);
}
});
snackbar.setActionTextColor(0xff0099ff);

snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT || event == Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE) {
MainActivity.database.receivedMessagesDao().archive(email, recentlyArchivedPeer);
MainActivity.database.sentMessagesDao().archive(email, recentlyArchivedPeer);
}
}
});

snackbar.show();
}

删除/归档一条消息时一切正常。在 Snackbar 消失后滑动删除或存档消息,当我单击撤消时,删除/存档被逆转。删除/归档多条消息时会出现问题。

问题 1: 当我删除/存档多条消息而不等待每条消息的 Snackbar 消失时,除第一条消息外的所有消息都被删除/存档。让我感到奇怪的是,不仅仅是最后一条消息被删除/存档,除了第一条消息之外的所有消息都被删除/存档。

问题 2: 当我删除/归档多条消息而不等待每条消息的 Snackbar 消失时,如果我按下 UNDO,即在 Snackbar 上为最后一条被删除的消息/存档,应用程序崩溃。

顺便说一下,我正在使用 Room Library 将消息存储在数据库中(由 MainActivity.database 引用)。

我认为问题出在 Snackbar 的 addCallback() 函数中。我应该为 event == Snackbar.Callback.DISMISS_EVENT_CONSECUTIVEevent == Snackbar.Callback.DISMISS_EVENT_TIMEOUT 做一些不同的事情,但我不知道到底是什么我应该采取不同的做法,以及究竟是什么导致了问题。

这是我的整个适配器类供引用(错误消息行旁边标有注释):

package com.example.treeapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.snackbar.Snackbar;
import com.mikhaellopez.circularimageview.CircularImageView;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class DonorMessagesAdapter extends RecyclerView.Adapter<DonorMessagesAdapter.DonorMessagesViewHolder> { // line 24 in error message
private Activity activity;
public String email;
public List<String> sortedPeers;
public static CircularImageView imageView;
private String recentlyDeletedPeer;
private int recentlyDeletedPeerPosition;
private String recentlyArchivedPeer;
private int recentlyArchivedPeerPosition;

public static class DonorMessagesViewHolder extends RecyclerView.ViewHolder {
public Button middleButton;
public TextView nameTextView;
public TextView messageTextView;

DonorMessagesViewHolder(View view) {
super(view);

middleButton = view.findViewById(R.id.middle_button);
imageView = view.findViewById(R.id.image_view);
nameTextView = view.findViewById(R.id.text_view_name);
messageTextView = view.findViewById(R.id.text_view_message);
}
}

DonorMessagesAdapter(Activity activity, String email) {
this.activity = activity;
this.email = email;
this.sortedPeers = getSortedPeers(email);
}

@NonNull
@Override
public DonorMessagesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message, parent, false);

return new DonorMessagesViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull DonorMessagesViewHolder holder, int position) {
final String current = sortedPeers.get(position);

// Start of getting last message
String lastMessage;
String lastMessageType;
List<Integer> receivedMessages = MainActivity.database.receivedMessagesDao().getMessagesToReceiverFromSender(email, current, 0);
List<Integer> sentMessages = MainActivity.database.sentMessagesDao().getMessagesBySenderToReceiver(email, current, 0);

if (sentMessages.size() == 0) {
lastMessage = MainActivity.database.receivedMessagesDao().getMessage(receivedMessages.get(receivedMessages.size() - 1)); // line 74 in error message
lastMessageType = "received";
if (MainActivity.database.receivedMessagesDao().getImage(receivedMessages.get(receivedMessages.size() - 1)) == 1) {
lastMessageType = "receivedImage";
}
} else if (receivedMessages.size() == 0) {
lastMessage = MainActivity.database.sentMessagesDao().getMessage(sentMessages.get(sentMessages.size() - 1));
lastMessageType = "sent";
if (MainActivity.database.sentMessagesDao().getImage(sentMessages.get(sentMessages.size() - 1)) == 1) {
lastMessageType = "sentImage";
}
} else {
LocalDateTime lastReceivedMessageTime = LocalDateTime.parse(MainActivity.database.receivedMessagesDao().getTime(receivedMessages.get(receivedMessages.size() - 1)));
LocalDateTime lastSentMessageTime = LocalDateTime.parse(MainActivity.database.sentMessagesDao().getTime(sentMessages.get(sentMessages.size() - 1)));

if (lastReceivedMessageTime.isAfter(lastSentMessageTime)) {
lastMessage = MainActivity.database.receivedMessagesDao().getMessage(receivedMessages.get(receivedMessages.size() - 1));
lastMessageType = "received";
if (MainActivity.database.receivedMessagesDao().getImage(receivedMessages.get(receivedMessages.size() - 1)) == 1) {
lastMessageType = "receivedImage";
}
} else {
lastMessage = MainActivity.database.sentMessagesDao().getMessage(sentMessages.get(sentMessages.size() - 1));
lastMessageType = "sent";
if (MainActivity.database.sentMessagesDao().getImage(sentMessages.get(sentMessages.size() - 1)) == 1) {
lastMessageType = "sentImage";
}
}
}
// End of getting last message

if (MainActivity.database.plantersDao().checkEmail(current) == 1) {
if (MainActivity.database.plantersDao().getImageUrl(current) != null) {
new DownloadImageTask(imageView).execute(MainActivity.database.plantersDao().getImageUrl(current));
}
} else if (MainActivity.database.donorsDao().checkEmail(current) == 1) {
if (MainActivity.database.donorsDao().getImageUrl(current) != null) {
new DownloadImageTask(imageView).execute(MainActivity.database.donorsDao().getImageUrl(current));
}
}

if (MainActivity.database.plantersDao().checkEmail(current) == 1) {
holder.nameTextView.setText(MainActivity.database.plantersDao().getName(current));
} else if (MainActivity.database.donorsDao().checkEmail(current) == 1) {
holder.nameTextView.setText(MainActivity.database.donorsDao().getName(current));
}

if (lastMessageType.equals("received")) {
if (lastMessage.length() > 17) {
holder.messageTextView.setText(lastMessage.substring(0, 16) + "...");
} else {
holder.messageTextView.setText(lastMessage);
}
} else if (lastMessageType.equals("sent")) {
if (lastMessage.length() > 12) {
holder.messageTextView.setText("You: " + lastMessage.substring(0, 11) + "...");
} else {
holder.messageTextView.setText("You: " + lastMessage);
}
} else if (lastMessageType.equals("receivedImage")) {
holder.messageTextView.setText("Image");
} else if (lastMessageType.equals("sentImage")) {
holder.messageTextView.setText("You: " + "Image");
}

holder.middleButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), MessageActivity.class);
intent.putExtra("email", email);
intent.putExtra("peerEmail", current);
intent.putExtra("archived", 0);

view.getContext().startActivity(intent);
}
});
}

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

public void reload() {
sortedPeers = getSortedPeers(email);
notifyDataSetChanged();
}

private List<String> getSortedPeers(String email) {
List<String> senders = MainActivity.database.receivedMessagesDao().getSendersForReceiver(email, 0);
List<String> receivers = MainActivity.database.sentMessagesDao().getReceiversForSender(email, 0);

List<String> peers = new ArrayList<>();
peers.addAll(senders);
peers.addAll(receivers);
peers = new ArrayList<>(new HashSet<>(peers));

List<String> sortedPeers = new ArrayList<>();
while (peers.size() > 0) {
LocalDateTime latestMessageTime = null;
String latestPeer = null;

for (String peer : peers) {
List<Integer> receivedMessages = MainActivity.database.receivedMessagesDao().getMessagesToReceiverFromSender(email, peer, 0);
List<Integer> sentMessages = MainActivity.database.sentMessagesDao().getMessagesBySenderToReceiver(email, peer, 0);

LocalDateTime lastMessageTime;
if (sentMessages.size() == 0) {
lastMessageTime = LocalDateTime.parse(MainActivity.database.receivedMessagesDao().getTime(receivedMessages.get(receivedMessages.size() - 1)));
} else if (receivedMessages.size() == 0) {
lastMessageTime = LocalDateTime.parse(MainActivity.database.sentMessagesDao().getTime(sentMessages.get(sentMessages.size() - 1)));
} else {
LocalDateTime lastReceivedMessageTime = LocalDateTime.parse(MainActivity.database.receivedMessagesDao().getTime(receivedMessages.get(receivedMessages.size() - 1)));
LocalDateTime lastSentMessageTime = LocalDateTime.parse(MainActivity.database.sentMessagesDao().getTime(sentMessages.get(sentMessages.size() - 1)));

if (lastReceivedMessageTime.isAfter(lastSentMessageTime)) {
lastMessageTime = lastReceivedMessageTime;
} else {
lastMessageTime = lastSentMessageTime;
}
}

if (latestMessageTime != null) {
if (lastMessageTime.isAfter(latestMessageTime)) {
latestMessageTime = lastMessageTime;
latestPeer = peer;
}
} else {
latestMessageTime = lastMessageTime;
latestPeer = peer;
}
}

sortedPeers.add(latestPeer);
peers.remove(latestPeer);
}

return sortedPeers;
}

public void deleteMessages(final int position) {
recentlyDeletedPeer = sortedPeers.get(position);
recentlyDeletedPeerPosition = position;

sortedPeers.remove(position);
notifyItemRemoved(position);

Snackbar snackbar = Snackbar.make(activity.findViewById(R.id.constraint_layout),
"Messages Deleted", Snackbar.LENGTH_LONG);
snackbar.setAction("UNDO", new View.OnClickListener() {
@Override
public void onClick(View view) {
sortedPeers.add(recentlyDeletedPeerPosition, recentlyDeletedPeer);
notifyItemInserted(recentlyDeletedPeerPosition);
}
});
snackbar.setActionTextColor(0xff0099ff);

snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT || event == Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE) {
MainActivity.database.receivedMessagesDao().deleteAllReceivedMessagesFromSender(email, recentlyDeletedPeer);
MainActivity.database.sentMessagesDao().deleteAllSentMessagesFromReceiver(email, recentlyDeletedPeer);
}
}
});

snackbar.show();
}

public void archiveMessages(final int position) {
recentlyArchivedPeer = sortedPeers.get(position);
recentlyArchivedPeerPosition = position;

sortedPeers.remove(position);
notifyItemRemoved(position);

Snackbar snackbar = Snackbar.make(activity.findViewById(R.id.constraint_layout),
"Messages archived", Snackbar.LENGTH_LONG);
snackbar.setAction("UNDO", new View.OnClickListener() {
@Override
public void onClick(View view) {
sortedPeers.add(recentlyArchivedPeerPosition, recentlyArchivedPeer);
notifyItemInserted(recentlyArchivedPeerPosition);
}
});
snackbar.setActionTextColor(0xff0099ff);

snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT || event == Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE) {
MainActivity.database.receivedMessagesDao().archive(email, recentlyArchivedPeer);
MainActivity.database.sentMessagesDao().archive(email, recentlyArchivedPeer);
reload();
}
}
});

snackbar.show();
}
}

这是我得到的错误(我的类标有 **):

2020-09-12 19:24:11.547 689-689/com.example.treeapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.treeapp, PID: 689
java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1
at java.util.ArrayList.get(ArrayList.java:439)
**at com.example.treeapp.DonorMessagesAdapter.onBindViewHolder(DonorMessagesAdapter.java:74)
at com.example.treeapp.DonorMessagesAdapter.onBindViewHolder(DonorMessagesAdapter.java:24)**
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1762)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:955)
at android.view.View.layout(View.java:20967)
at android.view.ViewGroup.layout(ViewGroup.java:6440)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3092)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2779)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1863)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8072)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)

最佳答案

要解决您的第一个问题,您可以尝试只检查解雇是否是由点击引起的,例如:

snackbar.addCallback(new Snackbar.Callback() {
@Override
public void onDismissed(Snackbar snackbar, int event) {
if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) {
MainActivity.database.receivedMessagesDao().deleteAllReceivedMessagesFromSender(email, recentlyDeletedPeer);
MainActivity.database.sentMessagesDao().deleteAllSentMessagesFromReceiver(email, recentlyDeletedPeer);
}
}
});

至于你的第二个问题,崩溃的发生是因为你只检查 sentMessages 列表是否为空

if (sentMessages.size() == 0) {
lastMessage = MainActivity.database.receivedMessagesDao().getMessage(receivedMessages.get(receivedMessages.size() - 1)); // line 74 in error message
lastMessageType = "received";
if (MainActivity.database.receivedMessagesDao().getImage(receivedMessages.get(receivedMessages.size() - 1)) == 1) {
lastMessageType = "receivedImage";
}
}

您在这里忘记做的是检查 reveivedMessages 是否也为空。例如:

if (sentMessages.size() == 0) {
if(receivedMessages.size() != 0) {
lastMessage = MainActivity.database.receivedMessagesDao().getMessage(receivedMessages.get(receivedMessages.size() - 1)); // line 74 in error message
lastMessageType = "received";
if (MainActivity.database.receivedMessagesDao().getImage(receivedMessages.get(receivedMessages.size() - 1)) == 1) {
lastMessageType = "receivedImage";
}
}
}

发生的情况是您的 receivedMessages 列表也是空的,这意味着您尝试获取位置 -1 的项目,这显然行不通。

即使这些技巧解决了您的问题,您也应该认真考虑如何访问数据库中的数据,因为您似乎在 UI 线程上执行所有调用,这是不可取的,因为它会阻塞 UI 线程。

关于android - 在 RecyclerView 中配置 ItemTouchHelper 以处理被显示的另一个 Snackbar 关闭的 Snackbar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63861451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com