【问题标题】:Two ArrayList one RecyclerView Adapter两个 ArrayList 一个 RecyclerView 适配器
【发布时间】:2017-07-15 23:36:24
【问题描述】:

我有一个聊天屏幕,我可以在其中与其他用户聊天,我正在向 RecyclerAdapter 发送聊天数据(消息、时间和通过列表的发送者),它用数据填充聊天视图。现在我还有一个列表,其中包含不同的数据布局。像这样

这是我将第二个数组列表调用到 RecyclerAdapter 的方法

public void TransferResultTo_Activity(List<Image_data_Wrapper> list) {
        Log.d(TAG,"Here is data Result From AsyncTask "+list.size());
        getResult=list;
        Image_data_Wrapper Image=getResult.get(0);
        Log.d(TAG,"Result from Image data "+Image.getPage_Title());
        adapter=new Chat_Adapter(this,message,getResult);
        adapter.notifyDataSetChanged();
    }

与上述方法一样,当我尝试通过recyclerView.setAdapter(adapter); 调用适配器时,它会从屏幕上删除所有消息并显示我的图像数据。但我想保留所有消息并通过新列表显示带有数据的图像

这是我的聊天适配器

public class Chat_Adapter extends RecyclerView.Adapter<Chat_Adapter.ViewHolder> {

    private String UserID;
    private Context context;
    //TAG FOR TRACKING SELF MESSAGE
    private int Self_Msg=0;
    //ARRAYLIST OF MESSAGES OBJECT CONTAINING ALL THE MESSAGES IN THE THREAD
    private List<Chat_Wrapper> arrayList_message;
    public static final String TAG="###CHAT_ADAPTER###";
    private List<Image_data_Wrapper> data_Result;
    boolean valtype;


    public Chat_Adapter(Context context, List<Chat_Wrapper> message) {
        //UserID = userID;
        this.context = context;
        this.arrayList_message = message;
        Log.d(TAG,"Chat Adapter Calling");
    }
    public Chat_Adapter(Context context, List<Image_data_Wrapper> result,boolean val) {
        this.context = context;
        this.data_Result = result;
        this.valtype=val;
        Log.d(TAG,"Image data Chat Adapter Calling");
    }

    public Chat_Adapter() {
    }


    @Override
    public Chat_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView;
        Log.d(TAG,"On Create View Holder Calling ");
        if (viewType==Self_Msg){
            itemView= LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_screen_message_item,parent,false);
            Log.d(TAG,"On Create View Holder Calling View Type is "+itemView);
        }

        else if (valtype==true){
            itemView= LayoutInflater.from(parent.getContext()).inflate(R.layout.Image_data_layout,parent,false);
            Log.d(TAG,"ON CREATE VIEW HOLDER RUNNING AND data RESULT VIEW TYPE IS RUNNING "+viewType);
        }

        else {
            itemView= LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_screen_message_item,parent,false);
            Log.d(TAG,"On Create View Holder Calling View Type is "+itemView);
        }
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(Chat_Adapter.ViewHolder holder, int position) {
        if (valtype==true){
            Image_data_Wrapper wrapper=data_Result.get(position);
            holder.data_title.setText(wrapper.getPage_Title());
            holder.data_link.setText(wrapper.getPage_Link());
            holder.data_snippet.setText(wrapper.getPage_Desc());
            Picasso.with(context).load(wrapper.getPage_ImageThumb()).into(holder.Image_Image);
            valtype=false;

        }
        else {

            Log.d(TAG,"On Bind VIew Holder Context "+context);
            Chat_Wrapper wrapper=arrayList_message.get(position);
            Log.d(TAG,"On Bind VIew Holder Chat Wrapper "+wrapper);
            holder.Message.setText(wrapper.getMessage());
            holder.TimeStamp.setText(wrapper.getTimestamp());

        }



    }

    @Override
    public int getItemCount() {
        Log.d(TAG,"Get Item Count Running");
        int items;
        if (valtype==true){
            Log.d(TAG,"data Result Array is not empty");
            items=data_Result.size();
            Log.d(TAG,"Total Number Of Item "+items);
            return items;
        }
        else {
            Log.d(TAG,"ARRAY SIZE AT GETITEM COUNT "+arrayList_message.size());
            return arrayList_message.size();
        }





    }


    @Override
    public int getItemViewType(int position) {
        Log.d(TAG,"Get Item View Type Running");
        return position;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView Message,TimeStamp,data_title,data_link,data_snippet;
        ImageView User_image,Image_Image;
        ImageButton data_SendButton;


         public ViewHolder(View itemView) {
             super(itemView);
             Message= (TextView) itemView.findViewById(R.id.Single_Item_Chat_Message);
             TimeStamp= (TextView) itemView.findViewById(R.id.Single_Item_Chat_TimeStamp);
             User_image= (ImageView) itemView.findViewById(R.id.Single_Item_Chat_ImageView);

             if (valtype==true){
                 Log.d(TAG,"Setting View For Image data ");
                 data_title= (TextView) itemView.findViewById(R.id.Image_data_Title);
                 data_link= (TextView) itemView.findViewById(R.id.Image_data_Link);
                 data_snippet= (TextView) itemView.findViewById(R.id.Image_data_Snippet);

                 Image_Image= (ImageView) itemView.findViewById(R.id.Image_data_Image);
                 data_SendButton= (ImageButton) itemView.findViewById(R.id.Image_data_SendButton);
             }




        }
    }

    public void updateDataWithdataResult(List<Image_data_Wrapper> list,boolean setValue){
        Log.d(TAG,"Update Data Method Calling");
        this.data_Result=list;
        this.valtype=setValue;
    }
}

这段代码我面临的问题

  • 在 notifiydatasetchanged 的​​情况下,只有适配器构造函数在调用(正确的一个),但从来没有 getItemCount()
  • 发送带有数据的布尔值是否是正确的检查方法,如果仅从 ImageArrayList 调用,则输入其相关数据或视图?
  • 将两个 List 放入具有自己布局的单个 RecyclerView 的最佳方法是什么

更新:当我通过recyclerView.setAdapter(adapter) 调用适配器时,它按我的意愿工作,但adapter.notifyDataSetChanged 使调用卡在适配器构造函数中(感谢 DanielLaneDC)。那我可以这样吗?还是adapter.notifyDataSetChanged 可以工作?

【问题讨论】:

  • 我说得对吗,从根本上说,您只是希望能够在一个 RecyclerView 中显示两个项目列表,由一个 RecyclerView.Adapter 处理?
  • @DanielLaneDC 是的,你说得对

标签: java android arraylist android-recyclerview


【解决方案1】:

我遇到了同样的问题。 如果需要,您可以创建一个 Pojo 类并输入关联,例如聊天可以有多个图像。然后构建聊天对象并在其中插入图像列表。 在将列表传递给适配器之前,用原始数据填充它。 我知道这可能不是满足您需求的好解决方案,但是 请记住,您可以完全控制,而无需对列表进行分段。

【讨论】:

    【解决方案2】:
    public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    class ViewHolder0 extends RecyclerView.ViewHolder {
        ...
        public ViewHolder0(View itemView){
        ...
        }
    }
    
    class ViewHolder2 extends RecyclerView.ViewHolder {
        ...
        public ViewHolder2(View itemView){
        ...
    }
    
    @Override
    public int getItemViewType(int position) {
        // Just as an example, return 0 or 2 depending on position
        // Note that unlike in ListView adapters, types don't have to be contiguous
        return position % 2 * 2;
    }
    
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         switch (viewType) {
             case 0: return new ViewHolder0(...);
             case 2: return new ViewHolder2(...);
             ...
         }
    }
    
    @Override
    public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
        switch (holder.getItemViewType()) {
            case 0:
                ViewHolder0 viewHolder0 = (ViewHolder0)holder;
                ...
                break;
    
            case 2:
                ViewHolder2 viewHolder2 = (ViewHolder2)holder;
                ...
                break;
        }
    }
    

    }

    【讨论】:

      【解决方案3】:

      听起来您想使用相同的 RecyclerView.Adapter 在相同的 RecyclerView 中显示两个不同的项目列表。谢天谢地,这是 RecyclerView.Adapter 可以很好地处理的事情。

      这是您的 RecyclerView.Adapter 的外观:

      public class ChatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
          final int VIEW_TYPE_MESSAGE = 0;
          final int VIEW_TYPE_IMAGE = 1;
      
          Context context;
          List<ChatWrapper> messages;
          List<ImageDataWrapper> images;
      
          public ChatAdapter(Context context, List<ChatWrapper> messages, List<ImageDataWrapper> images){
              this.context = context;
              this.messages = messages;
              this.images = images;
          }
      
          @Override
          public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
              if(viewType == VIEW_TYPE_MESSAGE){
                  return new MessageViewHolder(itemView);
              }
      
              if(viewType == VIEW_TYPE_IMAGE){
                  return new ImageViewHolder(itemView);
              }
      
              return null;
          }
      
          @Override
          public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position){
              if(viewHolder instanceof MessageViewHolder){
                  ((MessageViewHolder) viewHolder).populate(messages.get(position));
              }
      
              if(viewHolder instanceof ImageViewHolder){
                  ((ImageViewHolder) viewHolder).populate(images.get(position - messages.size()));
              }
          }
      
          @Override
          public int getItemCount(){
              return messages.size() + images.size();
          }
      
          @Override
          public int getItemViewType(int position){
              if(position < messages.size()){
                  return VIEW_TYPE_MESSAGE;
              }
      
              if(position - messages.size() < images.size()){
                  return VIEW_TYPE_IMAGE;
              }
      
              return -1;
          }
      
          public class MessageViewHolder extends RecyclerView.ViewHolder {
              TextView message;
              TextView timeStamp;
              ImageView userImage;
      
              public MessageViewHolder(View itemView){
                  super(itemView);
      
                  message = (TextView) itemView.findViewById(R.id.Single_Item_Chat_Message);
                  timeStamp = (TextView) itemView.findViewById(R.id.Single_Item_Chat_TimeStamp);
                  userImage = (ImageView) itemView.findViewById(R.id.Single_Item_Chat_ImageView);
              }
      
              public void populate(ChatWrapper chatWrapper){
                  message.setText(chatWrapper.getMessage());
                  userImage.setText(chatWrapper.getTimestamp());
              }
          }
      
          public class ImageViewHolder extends RecyclerView.ViewHolder {
              TextView dataTitle;
              TextView dataLink;
              TextView dataSnippet;
              ImageView image;
              ImageButton dataSendButton;
      
              public ImageViewHolder(View itemView){
                  super(itemView);
      
                  dataTitle = (TextView) itemView.findViewById(R.id.Image_data_Title);
                  dataLink = (TextView) itemView.findViewById(R.id.Image_data_Link);
                  dataSnippet = (TextView) itemView.findViewById(R.id.Image_data_Snippet);
                  image = (ImageView) itemView.findViewById(R.id.Image_data_Image);
                  dataSendButton = (ImageButton) itemView.findViewById(R.id.Image_data_SendButton);
              }
      
              public void populate(ImageDataWrapper imageDataWrapper){
                  dataTitle.setText(imageDataWrapper.getPage_Title());
                  dataLink.setText(imageDataWrapper.getPage_Link());
                  dataSnippet.setText(imageDataWrapper.getPage_Desc());
                  Picasso.with(context).load(imageDataWrapper.getPage_ImageThumb()).into(image);
              }
          }
      }
      

      这是您的Activity 需要的:

      List<ChatWrapper> messages;
      List<ImageDataWrapper> images;
      ChatAdapter adapter;
      
      @Override
      public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
      
          messages = new ArrayList<>();
          images = new ArrayList<>();
          ChatAdapter adapter = new ChatAdapter(this, messages, images);
      
          RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
          recyclerView.setLayoutManager(new LinearLayoutManager(this));
          recyclerView.setAdapter(adapter);
      }
      
      public void addMessage(ChatWrapper message){
          messages.add(message);
          adapter.notifyDataSetChanged();
      }
      
      public void removeMessage(ChatWrapper message){
          if(messages.remove(message)){
              adapter.notifyDataSetChanged();
          }
      }
      
      public void addImage(ImageDataWrapper image){
          images.add(image);
          adapter.notifyDataSetChanged();
      }
      
      public void removeImage(ImageDataWrapper image){
          if(images.remove(image)){
              adapter.notifyDataSetChanged();
          }
      }
      

      当您想更新数据时,只需调用addMessage(ChatWrapper)removeMessage(ChatWrapper) 获取消息,调用addImage(ImageDataWrapper)removeImage(ImageDataWrapper) 获取图像。

      一些关键点:

      • 您不想创建任何新的适配器或列表,您只想调用我们现有对象的方法。
      • 您的适配器应该表现得好像它总是必须处理消息和图像,但只是它可以处理 0 个消息或 0 个图像(没有valType 变量,getItemCount() 应该总是返回两个列表组合的大小,等)

      【讨论】:

      • 仍然卡在适配器构造器上,之后没有任何调用,日志显示每个数组列表的大小 Chat Adapter Calling 2 1 。我按照你说的做了,但还是不行
      • 我编辑了我的答案,包括您应该如何创建适配器。
      • 正如您在上面的代码中看到的那样,我在没有创建任何新的适配器或列表实例的情况下创建了//adapter=new Chat_Adapter(this,list,true);。所以我尝试了这个,但你的努力仍然没有运气。
      • 调用new Chat_Adapter 将创建一个新的适配器。在您的 TransferResultTo_Activity 方法中,您正在创建一个新适配器。您只需修改列表而不重新创建适配器,然后通过保留对传递给 RecyclerView 的同一适配器的引用来通知适配器。
      • 不,实际上我只是在测试那个时间,但正如你所说,我在上面的代码中使用了注释代码适配器
      【解决方案4】:

      首先,您需要将两个数组合并到单个数组列表中,例如.. firsArrlist.addAll(secondArrList);

      并传递到 recyclerview 适配器并使用一些标志进行迁移,并为特定标志获取另一个视图,以在 recyclerview 中设置该视图。

      并且总计数必须同时是 firstArrlist.size + secondArrList.size

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      • 2019-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多