This article belongs to serious literary subject, not science fiction, not dog blood. It takes about five minutes to read.
Original intention of the article: Because I now develop the project, there is a coexistence of ListView and Recyclerview. And because of various reasons, can not completely abandon ListView to Recyclerview bed. I’m sure many of you have encountered this problem in your development process, so the idea came up: could you make the adapters of these two components “universal”? Note: There are many ways to encapsulate an adapter, and this article provides only one idea.
Please start with the project address: an Adapter
Let’s talk about usage
1. Plain lists
- ListView
private ItemsAdapter mListAdapter;
mListAdapter = ItemsAdapter.create(this).putItemClass(TestItemView.class).build();
Copy the code
- Recyclerview
private RecyclerAdapter mRecyclerAdapter;
mRecyclerAdapter = RecyclerAdapter.create(this).putItemClass(TestItemView.class).build();
Copy the code
- The code of TestItemView class common to Recyclerview adapter and ListView adapter is as follows:
public class TestItemView extends AbsItemView<ItemBusiness, TestBean> { @Override protected void initView(Activity activity, ViewGroup parent, ItemBusiness itemBusiness, ViewHolderHelper holderHelper) { } @Override protected int getLayoutId() { return R.layout.item_layout; } @Override public void showItem(ViewHolderHelper holderHelper, TestBean itemData) { holderHelper.setText(R.id.test_tv, itemData.s); }}Copy the code
In initView (…) Method to set some properties of the View, such as width, height, transparency, etc. The data is set in showItem (…). Method, it’s important to note that both of these methods have a ViewHolderHelper argument, which is a utility class that I’ve wrapped. There are some common setText or setAlpha methods that use a Map to manage views, avoiding the need for findViewById and writing many View member variables. GetLayoutId () returns the layout Id.
Here I believe you can also see that my solution to Recyclerview and ListView adapter “universal” is to make them hold the same ItemView. If you need to change components, just change the code recyclerAdapter.create (this) to ItemsAdapter.create(this), or reverse. How about that? It’s so easy.
Making two component adapters “common” is a false proposition that requires different parameters. Since this way is not possible, then we might as well change the idea, let their ItemView common not to solve the problem.
The AbsItemView class is important and will be used in the next series of operations.
2. Elegantly implement multiple Item Type data binding
In the case of multiple Item types, the data binding AbsItemView is used. That is, one data type corresponds to one ItemType. Multi-item examples:
ItemsAdapter.create(this)
.putItemClass(TestItemView.class)
.putItemClass(TestOneItemView.class)
.build();
Copy the code
The code for TestOneItemView is almost identical to the code of TestItemView because it is a sample code. The only difference is that:
public class TestOneItemView extends AbsItemView<ItemBusiness, TestOneBean>
Copy the code
The data type of the TestOneItem binding is TestOneBean. Yes, you read that right. The binding between the data and the ItemView is done via generics. In the putItemClass method, we get the generic type by reflection, use hashCode as the key, and store the ItemView type into a map. Different ItemViews are generated for different data types when setting data.
Of course, if your custom ItemView does not rely on generics and wants to be set to a strongly bound type, this is also supported. PutItemClass (@nonnull Class
itemDataClass, @NonNull Class
> itemViewClass)
Click events and the business logic that itemView needs to handle
Click events are not handled by Adapter by default. You can set them using ListView’s native setOnItemClick. Alternatively, you can set the click event to the root View directly from within the AbsItemView.
- Click events and business logic are implemented through a single class, namely
ItemBusiness
ItemsAdapter.create(this) .putItemClass(TestItemView.class) .putItemClass(TestOneItemView.class) .setItemBusinessFactory(new ItemBusiness.Factory() { @Override public ItemBusiness create(AbsItemView itemView) { If (ItemView.ismatch (testOnebean.class)) {return new ItemBusiness(itemView) {return ItemBusiness(itemView) { @Override public void onItemClick() { super.onItemClick(); }}.setsetitemclick (true); } return null; } }) .build()Copy the code
Note that ItemBusin does not process click events by default and needs to be set to true via the setItemClick method to process click events within Business. I need to explain this class here. This class exists for the same purpose as the Presenter business processing class in MVP mode. We currently use MVP a lot in our projects, but have always felt that Presenter was not the right name. After discussing it with my friends, I decided it would be more appropriate to use the name Business.
- ItemBusiness itself provides many methods for processing business logic, such as clicking a button to refresh data, remove data, etc.
/ / refresh list public final void notifyDataSetChanged () {mAdapter. NotifyDataSetChanged (); Recyclerview Public Final void notifyItemDataChanged() {setItemData(mPosition, mItemData); } size public final int getCount() {return adapter.getitemCount (); Public final D getItemData() {return mItemData; } public final int getPosition() {return mPosition; }Copy the code
- Of course, you can also customize ItemBusiness, because during the development of the project, you may need to handle a lot of business logic in the ItemView. Such as web requests, interactive animations and so on.