java 两个 ArrayList 一个 RecyclerView Adapter

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42450466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:39:19  来源:igfitidea点击:

Two ArrayList one RecyclerView Adapter

javaandroidarraylistandroid-recyclerview

提问by androidXP

I have a chat screen where i can chat with other user, i am sending chat data (message,time and sender via List) to RecyclerAdapter which populate chat views with data.Now i have one more List which has data with different layout. Like this

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

Demo Screen

演示画面

Here is my method from where i am calling second arraylist into 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();
    }

As in above method when i try to call adapter by recyclerView.setAdapter(adapter);it remove all messages from screen and shows my image data. but i want to keep all messages and show image with data via new list

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

Here is my Chat 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;
    }
}

The issues i am facing with this code

我在使用此代码时遇到的问题

  • With notifiydatasetchanged only Adapter constructor is calling(Correct one) but never getItemCount()
  • Is sending boolean value with data is right way to check, If calls from ImageArrayList only then enter in its related data or views?
  • What is the best way to get both List into single RecyclerView with their own layout
  • 使用 notifydatasetchanged 仅适配器构造函数正在调用(正确的一个),但从未调用getItemCount()
  • 发送带有数据的布尔值是否是正确的检查方法,如果从 ImageArrayList 调用才输入其相关数据或视图?
  • 使用自己的布局将两个 List 放入单个 RecyclerView 的最佳方法是什么

UPDATE: When i call adapter by recyclerView.setAdapter(adapter)it worked as i want but adapter.notifyDataSetChangedmake call stuck at adapter constructor (Thanks to DanielLaneDC). So can i leave it like that or adapter.notifyDataSetChangedshould work?

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

回答by DanielLaneDC

It sounds like you want to show two different lists of items in the same RecyclerView using the same RecyclerView.Adapter. Thankfully, this is the kind of thing RecyclerView.Adapter can handle really nicely.

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

Here's how your RecyclerView.Adapter should look:

这是您的 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);
        }
    }
}

Here's what your Activityis going to need:

这是您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();
    }
}

When you want to update the data, just call addMessage(ChatWrapper)or removeMessage(ChatWrapper)for messages and addImage(ImageDataWrapper)or removeImage(ImageDataWrapper)for images.

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

Some key points:

一些关键点:

  • You don't want to create any new Adapters or Lists, you simply want to call methods on our existing objects.
  • Your Adapter should behave as if it always has to deal with messages and images, but just that it can handle 0 messages or 0 images (no valTypevariable, getItemCount()should always return the size of both lists combined, etc.)
  • 您不想创建任何新的适配器或列表,您只想调用我们现有对象上的方法。
  • 你的适配器应该表现得好像它总是必须处理消息和图像,但它可以处理 0 个消息或 0 个图像(没有valType变量,getItemCount()应该总是返回两个列表组合的大小等)

回答by Chirag.T

First you need to combine both array in single arraylist like.. firsArrlist.addAll(secondArrList);

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

and pass into recyclerview adapter and migrate with some flag and take another viewholder for particular flag to set that view in recyclerview.

并传入 recyclerview 适配器并使用一些标志进行迁移,并为特定标志采用另一个视图持有者以在 recyclerview 中设置该视图。

And total count is must both firstArrlist.size + secondArrList.size

总数必须是 firstArrlist.size + secondArrList.size

回答by Chirag.T

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;
    }
}

}

}

回答by AlexPad

I had your same problem. You can create a Pojo class if you need and enter the association for example a chat can have multiple images. Then build the chat object and insert a list of images in it. Before passing the list to the adapter, populate it with the original data. I know this may not be a nice solution for your needs, but remember that you can have full control, without segmenting the lists.

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