Are you struggling with the number of list styles in your project? Are you tired of writing Adapter code over and over again? Are you still going over and over again to write a multi-type card list with lots of details? It’s time to find a more efficient way to free yourself. NoAdapter – A component library developed to address Android lists.
As its name suggests, NoAdapter aims to create a simple RecycleView Adapter component that allows developers to focus more on the business’s own card (item) development. Ignore complex, tedious, repetitive (especially if a list has multiple card types) Adapter code development, do not need to develop a line of Adapter code, truly No Adapter.
Its advantages are as follows:
- Minimal, just one line of comment to complete the development, see the detailed usage introduction below;
- No dependency on data structures;
- Once used, the XXXAdapter class in the project can be completely destroyed.
A, how to use
1. Add dependencies and configurations
Add maven repository maven {url ‘https://jitpack.io’} to project root build.gradle
Add configurations and dependencies to build.gradle in module
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [ moduleName : 'xxxx' ]
}
}
}
}
dependencies{
implementation 'com.github.chenchongyu:NoAdapter-Library:vx.x.x'
annotationProcessor 'com.github.chenchongyu:NoAdapter-Compiler:vx.x.x'
}
Copy the code
At the same time, add the following obfuscation configuration:
-keep public class com.runningcode.noadapter.** { *; }
-keep public class * extends com.runningcode.noadapter.adpater.BaseVH
-keepattributes *Annotation*
Copy the code
2. Write the ViewHolder
Add the @viewholder annotation to extend the BaseVH class to specify the data type that the ViewHolder needs
@ViewHolder public class UserHolder extends BaseVH<User> { private ImageView imageView; public UserHolder(ViewGroup parent) { super(parent, R.layout.item_image); imageView = itemView.findViewById(R.id.image); } @Override public void bindData(User data) { imageView.setImageResource(data.image); }}Copy the code
Use 3.
The first step is to register it when the application is initialized (application is recommended).
ViewHolderRegistry.add(new ViewHolderRegistry_xxx());
ViewHolderRegistry.add(new ViewHolderRegistry_xxxxb());
Copy the code
The character after ViewHolderRegistry_ is the moduleName you configure in Gradle. Of course, you can skip this step, just add the following configuration to project and Module build.gradle: The classpath ‘com. Making. Chenchongyu: NoAdapter – Plugin: v1.0.0.1’ apply Plugin: ‘no – adapter – Plugin’
List allList = new ArrayList();
allList.add(new User());
NoAdapter adapter = new NoAdapter(allList);
mRecyclerView.setAdapter(adapter);
Copy the code
As above, a list page is developed, isn’t it easy?
2. Advanced usage
1. Add ItemClick event
NoAdapter adapter = newNoAdapter(allList);
adapter.setListener(newOnItemClickListener() {
@Override
publicvoidonItemClick(Object data) {
}
});
Copy the code
2. What if multiple types of cards in a list are not distinguished by data types, but by different fields within the same data type? So what?
For example, a list of chat messages that displays text messages, voice messages, picture messages, etc., depending on the type, returns the following data structure:
Class ChatMsg{ publicString msg; publicinttype; // 0: text; 1: voice; 2: the picture}Copy the code
In previous development, the developer could return the corresponding card type in the Adapter getItemType(), depending on the business, and then create different cards based on the type. Now we have no Adapter, so what should we do? Directly on the code:
@ViewHolder(cls = ChatMsg.class, filed = "type", type = 0) public class TextMsgViewHolder extends BaseVH<ChatMsg> { private TextView textView; private ImageView imageView; public News1ViewHolder(@NonNull ViewGroup parent) { super(parent, R.layout.item_msg_text); textView = itemView.findViewById(R.id.text); imageView = itemView.findViewById(R.id.image); } @Override public void bindData(ChatMsg data) { textView.setText(data.title); Glide.with(itemView.getContext()).load(data.url).into(imageView); } } @ViewHolder(cls = ChatMsg.class, filed = "type", type = 1) public class AudioMsgViewHolder extends BaseVH<ChatMsg> { private TextView textView; private ImageView imageView; public News1ViewHolder(@NonNull ViewGroup parent) { super(parent, R.layout.item_msg_audio); textView = itemView.findViewById(R.id.text); imageView = itemView.findViewById(R.id.image); } @Override public void bindData(ChatMsg data) { textView.setText(data.title); Glide.with(itemView.getContext()).load(data.url).into(imageView); }}Copy the code
As you can see, once again add the following annotation to the Viewholder
@ViewHolder(cls = ChatMsg.class, filed = "type", type = 1)
Just specify the corresponding data type, field name, and field value in the annotation.
To complete the demo project, go to noadapter-example
3. Basic principles
The basic idea is that with APT and reflection, we can use the @Viewholder annotation to collect all viewholders and their generic counterparts, register them in our own registry, and then when we use NoAdapter, Get ItemType and ViewHolder from the registry class.
Recyclerview. Adapter, override onCreateViewHolder, onBindViewHolder, getItemCount, etc. If your list has multiple types of items, then you have to rewrite getItemViewType again. By looking at it, getItemViewType returns an int representing the type of item. Then onCreateViewHolder creates the ViewHolder from this type, and then binds the data to the ViewHolder in onBindViewHolder. There are two key points here — how do YOU determine the itemType, and how do you determine the ViewHolder from the itemType?
If the class is a getItemViewType int, then the class is a getItemViewType int. If the class is a getItemViewType int, the class is a getItemViewType int. This is done using the Object hashCode method. Once you have identified the itemType, how do you identify the ViewHolder from the itemType? At the time of development, each ViewHolder knows what Class it is dealing with, so we can map all ClassType types to viewholders through a registry. So we can find the ViewHolder using the ItemType.
@ViewHolder public class UserHolder extends BaseVH<User>{} Copy the code
With the above declaration, we can find all ViewHolder classes and their required Object classes at compile time so that we can populate our registry. With a registry in place, the Adapter can be fully automated. The key code is as follows:
ItemType public int getItemViewType(int position) {return ViewHolderRegistry.getItemViewType(dataList.get(position)); } // Find ViewHolder public BaseVH<? > onCreateViewHolder(ViewGroup parent, int viewType) { Class<? > vhClass = ViewHolderRegistry.getVHClass(viewType); Constructor<? > constructor = vhClass.getConstructor(ViewGroup.class); BaseVH<? > viewHolder = (BaseVH<? >) constructor.newInstance(parent); return viewHolder; } public void onBindViewHolder(BaseVH holder, BaseVH holder) int position) { final Object data = dataList.get(position); holder.bindData(data); }Copy the code
See NoAdapter-Library for more information
discuss
QQ discussion group: 984012228