概述:我正在聊天应用程序。直到现在,我正在使用带有Listview的CursorAdapter来加载列表中的聊天项。但是现在,我计划重构代码以使用RecyclerView和RecyclerView.Adapter以及"加载更多"像whatsapp这样的功能。
问题:内存消耗。使用CursorAdapter,不在可查看区域的项目正在收集垃圾,但现在我使用我的CustomModal的ArrayList,一旦你加载列表中的所有项目(通过点击"加载更多&#34 ;按钮)我在内存日志中看到了高内存消耗(No Garbage Collection)。
我现在的猜测是,我正在加载ArrayList中的所有项目并导致问题。是吗?
有没有办法避免问题或优化问题?
修改 : 无法在此处发布完整代码,但这里是我已实施的适配器类型的片段:
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MyViewHolder> {
private ArrayList<MyModal> mMyModals;
public MessageAdapter(ArrayList<MyModal> mMyModals) {
this.mMyModals = mMyModals;
//... Some fields initialization here
}
public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){
this.mMyModals = myModals;
//... Some fields initialization here
notifyDataSetChanged();
}
public void toggleLoadMore(boolean isLoadMoreEnabled){
if(isLoadMoreEnabled){
//..Checks if load more is already enabled or not
//..If not then enables it by adding an item at 0th poition of MyModal list
//..Then notifyDataSetChanged()
}else{
//..Checks if load more is already disabled or not
//..If not then disables it by removing an item at 0th poition of MyModal list
//..Then notifyDataSetChanged()
}
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder messageViewHolder = null;
View itemLayoutView = null;
MyModal.MessageType messageType = MyModal.MessageType.getMessageTypeFromValue(viewType);
switch (messageType){
case MESSAGE_TYPE1:
itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout1, null);
messageViewHolder = new Type1ViewHolder(itemLayoutView);
break;
case MESSAGE_TYPE2:
itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout2, null);
messageViewHolder = new Type2ViewHolder(itemLayoutView);
break;
}
return messageViewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final MyModal myModal = mMyModals.get(position);
MyModal.MessageType messageType = myModal.getMessageType();
holder.initialize(myModal);
}
@Override
public int getItemCount() {
return (mMyModals != null)?mMyModals.size():0;
}
@Override
public int getItemViewType(int position) {
return mMyModals.get(position).getMessageType().getValue();
}
public abstract class MyViewHolder extends RecyclerView.ViewHolder {
public MyViewHolder(View itemLayoutView) {
super(itemLayoutView);
}
public abstract void initialize(MyModal myModal);
}
class Type1ViewHolder extends MyViewHolder {
//...Variables
public Type1ViewHolder(View itemLayoutView) {
super(itemLayoutView);
//...variables initialization here
}
@Override
public void initialize(MyModal myModal) {
//...Setting values in view using myModal
}
}
class Type2ViewHolder extends MyViewHolder {
//...Variables
public TextViewHolder(View itemLayoutView) {
super(itemLayoutView);
//...variables initialization here
}
@Override
public void initialize(MyModal myModal) {
//...Setting values in view using myModal
}
}
}
答案 0 :(得分:2)
首先:
public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){
this.mMyModals = myModals;
//... Some fields initialization here
notifyDataSetChanged();
}
在这里,您将创建一个新的arraylist并将其分配给您的mMyModals。这意味着此时有2个arraylists,它们占用的空间量是所需空间的两倍。 GC没有按照你期望的方式工作。由于arraylist在你的活动中初始化,只要arraylist持续存在,它就会持续存在,而最初的arraylist也会如此。
而不是在您的活动中创建新的arraylist并将其传递给changeList。只需清除旧的arraylist并传递它。并且在适配器changeList方法中,您可以执行以下操作
public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){
this.mMyModals.clear();
this.mMyModels.addAll(myModels);
//... Some fields initialization here
notifyDataSetChanged();
}
如果我不清楚,请告诉我。如果这不起作用,也会显示您的活动代码。
答案 1 :(得分:1)
请尝试将项目添加到ArrayList
,然后调用notifyDataSetChanged
,而不是替换整个ArrayList
并调用notifyItemRangeInserted(int positionStart, int itemCount)
,这可能会有效。此外,您无需替换Adapter
&#39; ArrayList
。您的Activity
/ Fragment
可能具有相同的ArrayList
,只需在Activity
/ Fragment
中修改此列表,然后调用notifyItemRangeInserted(int positionStart, int itemCount)
即可特技。此外,您还可以尝试仅获取下一个X消息,而不是检索所有消息,因此您不会检索之前已检索过的消息(如果您还没有这样做)。