我正在处理一个聊天应用程序,我有一些问题显示聊天消息。对于存储,我使用了一个Room数据库,为了显示消息,我使用了一个RecyclerView。问题是,activity变得非常慢,在滚动信息时没有那么好的响应。
下面是我的代码:
ChatActivity.java
public class ChatActivity extends AppCompatActivity {
public static final String TAG = ChatActivity.class.getSimpleName();
public static Contact contact;
public static boolean isContactConnected;
private CircleImageView mContactPicture;
private ImageView mContactConnected;
private TextView mContactName;
private TextView mContactStatus;
private ChatAdapter mChatAdapter;
private RecyclerView mRecyclerView;
private EmojiconEditText mUserMessageInput;
private View rootView;
private ImageView emojiImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
initializeToolbar();
String contactPhone = Objects.requireNonNull(getIntent().getStringExtra("phone"));
contact = MainActivity.db.getContactDao().findByPhone(contactPhone);
if (MainActivity.notificationMessages.get(contact.getId()) != null) {
MainActivity.notificationMessages.put(contact.getId(), new ArrayList<Message>());
}
updateUI(contact);
initializeViews();
initializeRecyclerView();
EmojIconActions emojIconActions = new EmojIconActions(this, rootView, mUserMessageInput, emojiImageView);
emojIconActions.ShowEmojIcon();
emojIconActions.setIconsIds(R.drawable.ic_baseline_keyboard_24, R.drawable.ic_baseline_emoji_emotions_24);
mChatAdapter = new ChatAdapter(this, new ArrayList<Message>());
mRecyclerView.setAdapter(mChatAdapter);
MainActivity.db.getMessageDao().getLiveMessages(contactPhone).observe(this, new Observer<List<Message>>() {
@Override
public void onChanged(List<Message> newMessages) {
mChatAdapter.setMessages(newMessages);
mRecyclerView.scrollToPosition(newMessages.size() - 1);
}
});
}
[...]
private void updateUI(Contact contact) {
mContactName.setText(contact.getName());
if (!contact.isConnected()) {
Date currentTime = Calendar.getInstance().getTime();
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.US);
isContactConnected = false;
mContactStatus.setText(
String.format(
"Last seen %s",
DateManager.getLastActiveText(
df.format(currentTime),
contact.getLastActive()
)
)
);
mContactConnected.setVisibility(View.GONE);
Log.d(TAG, "updateUI: initialized contact UI as disconnected");
} else {
mContactStatus.setText(R.string.active_now);
mContactConnected.setVisibility(View.VISIBLE);
isContactConnected = true;
Log.d(TAG, "updateUI: initialized contact UI as connected");
}
if (contact.getPhotoUri() != null) {
Uri imageUri = Uri.parse(contact.getPhotoUri());
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
mContactPicture.setImageBitmap(bitmap);
Log.d(TAG, "updateUI: loaded contact photo from device");
} catch (IOException e) {
Toast.makeText(
ChatActivity.this,
"Failed to load image from device.",
Toast.LENGTH_SHORT
).show();
e.printStackTrace();
}
}
}
[...]
private void initializeRecyclerView() {
mRecyclerView = findViewById(R.id.chat_recycler_view);
RecyclerView.LayoutManager layoutManager =
new LinearLayoutManager(ChatActivity.this, LinearLayoutManager.VERTICAL, false);
mRecyclerView.setLayoutManager(layoutManager);
Log.d(TAG, "initializeRecyclerView: initialized RecyclerView");
}
[...]
}
AppDatabase.java
@Database(entities = {Contact.class, Message.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class AppDatabase extends RoomDatabase {
public abstract ContactDao getContactDao();
public abstract MessageDao getMessageDao();
}
MessageDao.java
@Dao
public interface MessageDao {
@Query("SELECT * FROM messages WHERE to_from = :contact ORDER BY timestamp")
List<Message> getMessages(String contact);
@Query("SELECT * FROM messages WHERE to_from = :contact ORDER BY timestamp")
LiveData<List<Message>> getLiveMessages(String contact);
@Query("SELECT * FROM messages WHERE to_from =:contact AND status = 0")
List<Message> getUndeliveredMessages(String contact);
@Query("SELECT * FROM messages WHERE payloadId = :payloadId LIMIT 1")
Message getMessageByPayloadId(long payloadId);
@Query("SELECT * FROM messages WHERE to_from = :contact ORDER BY timestamp DESC LIMIT 1")
Message getLastMessage(String contact);
@Query("SELECT * FROM messages WHERE to_from = :contact ORDER BY timestamp DESC LIMIT 1")
LiveData<Message> getLastLiveMessage(String contact);
@Query("DELETE FROM messages")
void deleteAllMessages();
@Insert
void addMessage(Message message);
@Update
void updateMessage(Message message);
@Delete
void deleteMessage(Message message);
}
ChatAdapter.java
public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mContext;
private List<Message> messages;
public ChatAdapter(Context context, List<Message> messages) {
this.mContext = context;
this.messages = messages;
}
@Override
public int getItemViewType(int position) {
Message message = messages.get(position);
int status = message.getStatus();
if (status == Message.RECEIVED) {
return 0;
} else {
return 1;
}
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
if (viewType == 0) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_message_item, parent, false);
return new ChatUserViewHolder(itemView);
}
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_message_item2, parent, false);
return new ChatOtherViewHolder(itemView);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
Message currentMessage = messages.get(position);
String messageContent = currentMessage.getContent();
Date date = currentMessage.getTimestamp();
SimpleDateFormat ft = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.US);
Date currentDate = Calendar.getInstance().getTime();
switch (getItemViewType(position)) {
case 0:
ChatUserViewHolder mHolder = (ChatUserViewHolder) holder;
Contact sender = MainActivity.db.getContactDao().findByPhone(currentMessage.getToFrom());
if (sender.getPhotoUri() != null) {
Uri imageUri = Uri.parse(sender.getPhotoUri());
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), imageUri);
mHolder.getSenderProfilePicture().setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
mHolder.getSenderName().setText(sender.getName());
mHolder.getMessageContent().setText(messageContent);
mHolder.getTimestamp().setText(DateManager.getLastActiveText(ft.format(currentDate), ft.format(date)));
break;
case 1:
ChatOtherViewHolder nHolder = (ChatOtherViewHolder) holder;
SharedPreferences sharedPreferences = mContext.getSharedPreferences("LOGIN_DETAILS", MODE_PRIVATE);
String name = sharedPreferences.getString("name", "");
String photoUri = sharedPreferences.getString("photoUri", null);
if (photoUri != null) {
Uri imageUri = Uri.parse(photoUri);
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), imageUri);
nHolder.getSenderProfilePicture().setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
nHolder.getSenderName().setText(name);
nHolder.getMessageContent().setText(messageContent);
nHolder.getTimestamp().setText(DateManager.getLastActiveText(ft.format(currentDate), ft.format(date)));
if (currentMessage.getStatus() == Message.SENT) {
nHolder.getMessageStatus().setImageResource(R.drawable.ic_baseline_done_24);
} else {
nHolder.getMessageStatus().setImageResource(R.drawable.ic_baseline_done_all_24);
}
break;
default:
break;
}
}
@Override
public int getItemCount() {
return messages.size();
}
public void setMessages(List<Message> messages) {
if (this.messages.size() > 0) {
this.messages.clear();
}
this.messages = messages;
notifyDataSetChanged();
}
ChatitemViewWholder.java
class ChatItemViewHolder extends RecyclerView.ViewHolder {
private CircleImageView mUserProfilePic;
private ImageView mUserStatus;
private TextView mUserProfileName;
private EmojiconTextView mLastMessage;
private TextView mTimestamp;
public ChatItemViewHolder(@NonNull View itemView) {
super(itemView);
mUserProfilePic = itemView.findViewById(R.id.contact_image_item);
mUserProfileName = itemView.findViewById(R.id.contact_name_item);
mUserStatus = itemView.findViewById(R.id.status);
mLastMessage = itemView.findViewById(R.id.contact_status_item);
mTimestamp = itemView.findViewById(R.id.timestamp);
}
public CircleImageView getUserProfilePic() {
return mUserProfilePic;
}
public ImageView getUserStatus() {
return mUserStatus;
}
public TextView getUserProfileName() {
return mUserProfileName;
}
public EmojiconTextView getLastMessage() {
return mLastMessage;
}
public TextView getTimestamp() {
return mTimestamp;
}
}
chatotherviewholder.java
class ChatOtherViewHolder extends RecyclerView.ViewHolder {
private CircleImageView mSenderProfilePicture;
private TextView mSenderName;
private EmojiconTextView mMessageContent;
private TextView mTimestamp;
private ImageView mMessageStatus;
public ChatOtherViewHolder(@NonNull View itemView) {
super(itemView);
mSenderProfilePicture = itemView.findViewById(R.id.sender_profile_pic);
mSenderName = itemView.findViewById(R.id.sender_name);
mMessageContent = itemView.findViewById(R.id.message_content);
mTimestamp = itemView.findViewById(R.id.message_timestamp);
mMessageStatus = itemView.findViewById(R.id.message_status);
}
public CircleImageView getSenderProfilePicture() {
return mSenderProfilePicture;
}
public TextView getSenderName() {
return mSenderName;
}
public EmojiconTextView getMessageContent() {
return mMessageContent;
}
public TextView getTimestamp() {
return mTimestamp;
}
public ImageView getMessageStatus() {
return mMessageStatus;
}
}
显然问题出在房车上。最初我认为在UI线程上运行的observe方法可能会导致问题,但我替换了onChanged方法中的操作,UI非常流畅,所以只有在尝试更新RV项时才会出现问题。
我能做些什么来解决这个问题?
我看到了两个大问题
>
永远不要在适配器中进行数据库调用,数据库调用在适配器中使用太贵了。
您还可以将整个位图加载到内存中,使用像Glide这样的图像加载库来加载图像,它们处理回收的视图,并将图像调整到所需的大小,同时进行异步加载
问题内容: 我之所以这样问是因为我使用Python,但是它也可以应用于其他解释语言(Ruby,PHP,JavaScript)。 每当我在代码中留下评论时,我是否会放慢解释器的速度?根据我对解释器的有限了解,它以字符串形式读取程序表达式,然后将这些字符串转换为代码。似乎每次解析评论时都是浪费时间。 是这样吗 是否有一些解释性语言的注释约定,或者其影响可以忽略不计? 问题答案: 对于Python而言,
RecycerView只显示创建时ArrayList(适配器的数据)中的项。我所有添加更多行的尝试似乎都奏效了,但列表仍然是初始数据。它不是重复的,因为我尝试了谷歌上找到的所有建议。我已经做了什么: Adapter.NotifyDataSetChanged(); Adapter.NotifyItemChanged(5); recyleList.invalidate(); recyclelist.s
我使用ElasticSearch 5.6。 运行快照时,我运行http://localhost:9200/_cluster/health但在10秒以上没有得到回应。我还可以看到,当快照运行时,机器在磁盘/网络IO方面有很多成本。 如果我不运行快照,这样的延迟不会发生。 我用超时检查_cluster/健康状况,以确保创建快照不会减慢查询速度。这是检查的正确方法吗?在实践中,创建快照会使查询变慢吗?
我正在从ListView迁移到RecyclerView,但是在SQLite中输入一些数据之后,我的列表没有使用notifyDataSetChanged()更新;所以我总是必须调用setAdapter()方法; 回收器ViewAdapter 观赏者 模型
> 从创建的片段中更新,将新数据设置为adapter,然后调用;但没有奏效。 像其他人一样创建一个新适配器,它对他们起作用,但对我没有任何改变: 在中创建一个更新数据的方法,如下所示: 问题是gridView的布局如下所示: 然后我只是删除了并将作为父布局。
试图弄清楚更新的适配器有什么问题。 在我得到一个新的产品列表后,我尝试: > 从创建的片段中更新,将新数据设置到adapter,然后调用;但没有奏效。 像其他人一样创建一个新适配器,它对他们有效,但对我没有任何改变: 在中创建一个更新数据的方法,如下所示: 然后每当我想要更新数据列表时,我就调用这个方法;但没有奏效。 检查是否可以以任何方式修改recyclerView,并且我尝试至少删除一个项目: