如何重用 RecyclerView 对象、适配器和视图持有者

Posted

技术标签:

【中文标题】如何重用 RecyclerView 对象、适配器和视图持有者【英文标题】:How to reuse RecyclerView objects, adapters and view holders 【发布时间】:2016-04-24 09:54:01 【问题描述】:

在我的应用程序中,我有一系列以前称为 listViews 的东西,现在是 RecyclerViews。我很好奇提高模块化和减少应用程序这一部分重复的最有效方法。

例如,我有GroupMemberFragmentFriendFragment,它们具有几乎相同的RecyclerView.ViewHoldersRecyclerView.Adapters

重构以减少代码重复但仍允许每个相应的项目列表对其数据唯一且足够灵活以在未来添加更多数据的最佳方法是什么?

GroupMemberFragment

public class GroupMemberFragment extends Fragment 

    RecyclerView mRecyclerView;
    ArrayList<Group> mGRoups;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
    

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

        View view = inflater.inflate(R.layout.recycler_layout, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_layout);
        mRecyclerView.setHasFixedSize(true);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        // Only things that need to change across all the list classes....
        mGRoups = GroupListProvider.getInstance(getActivity()).getGroups();
        mRecyclerView.setAdapter(new GroupAdapter(mGRoups));

        return view;
    


    // inner Class

    private class GroupViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener 
        private final TextView mName;
        private final TextView mChannel;

        public GroupViewHolder(View itemView) 
            super(itemView);

            mName = (TextView) itemView.findViewById(R.id.tv_name);
            mChannel = (TextView) itemView.findViewById(R.id.tv_number);

            mName.setOnClickListener(this);
        

        public void bindGroup(Group group)
            mName.setText(group.getName().toString());
            mChannel.setText(group.getGroupChannelID().toString());
        

        @Override
        public void onClick(View view) 
            int itemPosition = getAdapterPosition();
            Toast.makeText(getContext(), "Position is: " + String.valueOf(itemPosition), Toast.LENGTH_LONG).show();
        
    


    class GroupAdapter extends RecyclerView.Adapter<GroupViewHolder> 
        ArrayList<Group> groupList;

        GroupAdapter(ArrayList<Group> object)
            this.groupList = object;
        

        @Override
        public GroupViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.rv_item, parent, false);

            return new GroupViewHolder(view);

        

        @Override
        public void onBindViewHolder(GroupViewHolder holder, int position) 

            Group group = groupList.get(position);
            holder.bindGroup(group);
        

        @Override
        public int getItemCount() 
            return groupList.size();
        
    

FriendFragment

public class FriendFragment extends Fragment 

    RecyclerView mRecyclerView;
    ArrayList<Friend> mContacts;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
    

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 

        View view = inflater.inflate(R.layout.recycler_layout, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view_layout);
        mRecyclerView.setHasFixedSize(true);

        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

        mContacts = FriendProvider.getInstance(getActivity()).getFriends();
        mRecyclerView.setAdapter(new ContactAdapter(mContacts));

        return view;
    

    // Inner Class

    private class ContactViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
        private final TextView mName;
        private final TextView mNumber;
        private Friend mContact;

        public ContactViewHolder(View itemView) 
            super(itemView);

            mName = (TextView) itemView.findViewById(R.id.tv_name);
            mNumber = (TextView) itemView.findViewById(R.id.tv_number);

            mName.setOnClickListener(this);
        

        public void bindContact(Friend contact)
            mContact = contact;
            mName.setText(contact.getFirstName().toString() + " " + contact.getLastName());
            mNumber.setText(contact.getFriendChannelID().toString());
        

        @Override
        public void onClick(View view) 
            int itemPosition = getAdapterPosition();
            Toast.makeText(getContext(), "Position is: " + String.valueOf(itemPosition), Toast.LENGTH_LONG).show();
        

    

    class ContactAdapter extends RecyclerView.Adapter<ContactViewHolder> 
        ArrayList<Friend> contactList;

        ContactAdapter(ArrayList<Friend> object)
            this.contactList = object;
        

        @Override
        public ContactViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.rv_item, parent, false);

            return new ContactViewHolder(view);

        

        @Override
        public void onBindViewHolder(ContactViewHolder holder, int position) 

            Friend contact = contactList.get(position);
            holder.bindContact(contact);
        


        @Override
        public int getItemCount() 
            return contactList.size();
        
    

【问题讨论】:

嗨!您说“将来添加更多数据”是什么意思?你要做出哪些改变?现在看来您的适配器几乎没有共同点(除了两者都有列表数据) 你最后做了什么? 【参考方案1】:

您可以为您的对象创建创建工厂方法以使其更整洁,但您的代码并没有紧密耦合,它看起来很草率,因为您两次做同样的事情,但是他们正在做完全独立的事情,所以要么离开它,要么,用一些对象工厂或应用程序类变量清理它

【讨论】:

代码“马虎”是怎么回事?怎么清理?【参考方案2】:

您可以从两个类中取出适配器类,并为其创建一个单独的 Java 文件,并为您拥有的两个类使用相同的适配器。 为此,您可以为适配器创建两个不同的构造函数并实现它。

【讨论】:

请举例说明你的答案

以上是关于如何重用 RecyclerView 对象、适配器和视图持有者的主要内容,如果未能解决你的问题,请参考以下文章

recyclerview 适配器如何知道调用 onCreateViewHolder?

将对象列表从片段传递到 recyclerView 适配器

从RecyclerView适配器更新活动或片段的视图

如何在 Kotlin 中使用与 Activity 和 Fragment 相同的 RecyclerView 适配器?

如何在 MVVM 架构中观察 RecyclerView 适配器中的 LiveData?

如何使用 DiffUtil 更新 RecyclerView 适配器