RecyclerView中有大量项目.适配器-内存问题



概述:我有一个聊天应用程序。到目前为止,我一直在使用带有Listview的CursorAdapter来加载列表中的聊天项目。但现在,我计划重构代码,将RecyclerView与RecyclerView.Adapter和类似whatsapp的"加载更多"功能一起使用。

问题:内存消耗。使用CursorAdapter,不在可视区域中的项目会被垃圾回收,但现在由于我使用的是CustomModal的ArrayList,一旦你加载了列表中的所有项目(通过单击"加载更多"按钮),我就会在内存日志中看到高内存消耗(无垃圾回收)。

我的猜测是,现在我正在加载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
        }
    }
}

首先:

   public void changeList(ArrayList<MyModal> myModals, boolean isLoadMoreEnabled){
    this.mMyModals = myModals;
    //... Some fields initialization here
    notifyDataSetChanged();
}

在这里,您正在创建一个新的数组列表,并将其分配给您的mMyModals。这意味着此时有2个数组,它们占用的空间是所需空间的两倍。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();
}

如果我不清楚,请告诉我。如果不起作用,还显示您的活动代码。

不要替换整个ArrayList并调用notifyDataSetChanged,而是尝试将项添加到ArrayList,然后调用notifyItemRangeInserted(int positionStart, int itemCount),也许这样可以。此外,您不必更换AdapterArrayList。您的Activity/Fragment可能具有相同的ArrayList,只需在Activity/Fragment中编辑此列表,然后调用notifyItemRangeInserted(int positionStart, int itemCount)即可。此外,您也可以尝试只获取下一个X数量的消息,而不是检索所有消息,这样您就不会检索以前已经检索到的消息(如果您还没有这样做的话)。

最新更新