2.5.0 Building a Reusable Custom BaseAdapter
Category Android Basic Tutorial
Introduction to This Section:
>
As the title suggests, this section is about building a reusable custom BaseAdapter. Every time we deal with ListView, GridView, and other adapter controls, we have to write a separate BaseAdapter class, which is quite troublesome. For instance, if we want to display two ListViews on one interface, we would also need to write two BaseAdapters... Well, programmers like to take shortcuts, right? In this section, we will write a reusable custom BaseAdapter class~
1. Let's Start Gradually:
First, let's post the custom BaseAdapter we wrote in the previous section, which we will upgrade and transform later.
/**
* Created by Jay on 2015/9/21 0021.
*/
public class MyAdapter extends BaseAdapter {
private Context mContext;
private LinkedList<Data> mData;
public MyAdapter() {
}
public MyAdapter(LinkedList<Data> mData, Context mContext) {
this.mData = mData;
this.mContext = mContext;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list, parent, false);
holder = new ViewHolder();
holder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
return convertView;
}
// Add an element
public void add(Data data) {
if (mData == null) {
mData = new LinkedList<>();
}
mData.add(data);
notifyDataSetChanged();
}
// Add an element at a specific position
public void add(int position, Data data){
if (mData == null) {
mData = new LinkedList<>();
}
mData.add(position, data);
notifyDataSetChanged();
}
public void remove(Data data) {
if(mData != null) {
mData.remove(data);
}
notifyDataSetChanged();
}
public void remove(int position) {
if(mData != null) {
mData.remove(position);
}
notifyDataSetChanged();
}
public void clear() {
if(mData != null) {
mData.clear();
}
notifyDataSetChanged();
}
private class ViewHolder {
ImageView img_icon;
TextView txt_content;
}
}
Upgrade 1: Set Entity as a Generic Type
Alright, since the Entity class we pass may vary greatly, such as Person, Book, Weather, etc., we will set Entity as a generic type. The modified code is as follows:
public class MyAdapter<T> extends BaseAdapter {
private Context mContext;
private LinkedList<T> mData;
public MyAdapter() {
}
public MyAdapter(LinkedList<T> mData, Context mContext) {
this.mData = mData;
this.mContext = mContext;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list, parent, false);
holder = new ViewHolder();
holder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
return convertView;
}
// Add an element
public void add(T data) {
if (mData == null) {
mData = new LinkedList<>();
}
mData.add(data);
notifyDataSetChanged();
}
// Add an element at a specific position
public void add(int position, T data){
if (mData == null) {
mData = new LinkedList<>();
}
mData.add(position, data);
Control ID, and the content set, such as setting the text of a TextView:
public ViewHolder setText(int id, CharSequence text) {Text setting}
- Move the convertView reuse part here, then you need to pass a context object, and we write the parts that need to be obtained into the constructor method!
- Write a bunch of setting methods (public), such as setting text size, color, picture background, etc.!
Okay, let's transform our ViewHolder class step by step.
---
### 1) Related parameters and constructor method:
public static class ViewHolder {
private SparseArray<View> mViews; //Stores the Views in the ListView item
private View item; //Stores the convertView
private int position; //Cursor
private Context context; //Context
//Constructor method, completes the relevant initialization
private ViewHolder(Context context, ViewGroup parent, int layoutRes) {
mViews = new SparseArray<>();
this.context = context;
View convertView = LayoutInflater.from(context).inflate(layoutRes, parent, false);
convertView.setTag(this);
item = convertView;
}
ImageView img_icon;
TextView txt_content;
}
---
### 2) Binding ViewHolder and Item
On the basis of the above, we add a binding method
//Bind ViewHolder and item public static ViewHolder bind(Context context, View convertView, ViewGroup parent, int layoutRes, int position) { ViewHolder holder; if(convertView == null) { holder = new ViewHolder(context, parent, layoutRes); } else { holder = (ViewHolder) convertView.getTag(); holder.item = convertView; } holder.position = position; return holder; }
---
### 3) Get the saved control in the collection according to the id
public <T extends View> T getView(int id) { T t = (T) mViews.get(id); if(t == null) { t = (T) item.findViewById(id); mViews.put(id, t); } return t; }
### 4) Then we define a bunch of exposed methods
/**
- Get the current item */ public View getItemView() { return item; }
/**
- Get the item position */ public int getItemPosition() { return position; }
/**
- Set text */ public ViewHolder setText(int id, CharSequence text) { View view = getView(id); if(view instanceof TextView) { ((TextView) view).setText(text); } return this; }
/**
- Set image */ public ViewHolder setImageResource(int id, int drawableRes) { View view = getView(id); if(view instanceof ImageView) { ((ImageView) view).setImageResource(drawableRes); } else { view.setBackgroundResource(drawableRes); } return this; }
/**
- Set click listener */ public ViewHolder setOnClickListener(int id, View.OnClickListener listener) { getView(id).setOnClickListener(listener); return this; }
/**
- Set visibility */ public ViewHolder setVisibility(int id, int visible) { getView(id).setVisibility(visible); return this; }
/**
- Set tag */ public ViewHolder setTag(int id, Object obj) { getView(id).setTag(obj); return this; }
//Other methods can be expanded by yourself
Okay, the transformation and upgrade of ViewHolder is completed~
---
## Upgrade 3: Define an abstract method to complete the binding of ViewHolder and Data dataset
public abstract void bindView(ViewHolder holder, T obj);
When we create a new BaseAdapter, we just need to implement this method, and don't forget to change our custom BaseAdapter to abstract!
---
## Upgrade 4: Modify the content of getView()
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutRes , position); bindView(holder,getItem(position)); return holder.getItemView(); }
---
## 2. Upgrade is complete, let's write code to experience it:
The effect we want to achieve:
There are two lists above, with different layouts, but I only use one BaseAdapter class to achieve the above effect!
The key code is as follows:
**MainActivity.java** :
public class MainActivity extends AppCompatActivity {
private Context mContext;
private ListView list_book;
private ListView list_app;
private MyAdapter<App> myAdapter1 = null;
private MyAdapter<Book> myAdapter2 = null;
private List<App> mData1 = null;
private List<Book> mData2 = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
init();
}
private void init() {
list
The reusable BaseAdapter we wrote is used as described above.
3. Code Sample Download:
Let's post the final MyAdapter class we wrote, which can be expanded according to your own needs:
MyAdapter.java :
```java /**
- Created by Jay on 2015/9/22 0022. */ public abstract class MyAdapter<T> extends BaseAdapter {
private ArrayList<T> mData;
private int mLayoutRes; // Layout ID
public MyAdapter() {
}
public MyAdapter(ArrayList<T> mData, int mLayoutRes) {
this.mData = mData;
this.mLayoutRes = mLayoutRes;
}
@Override
public int getCount() {
return mData != null ? mData.size() : 0;
}
@Override
public T getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutRes
, position);
bindView(holder, getItem(position));
return holder.getItemView();
}
public abstract void bindView(ViewHolder holder, T obj);
// Add an element
public void add(T data) {
if (mData == null) {
mData = new ArrayList<>();
}
mData.add(data);
notifyDataSetChanged();
}
// Add an element at a specific position
public void add(int position, T data) {
if (mData == null) {
mData = new ArrayList<>();
}
mData.add(position, data);
notifyDataSetChanged();
}
public void remove(T data) {
if (mData != null) {
mData.remove(data);
}
notifyDataSetChanged();
}
public void remove(int position) {
if (mData != null) {
mData.remove(position);
}
notifyDataSetChanged();
}
public void clear() {
if (mData != null) {
mData.clear();
}
notifyDataSetChanged();
}
public static class ViewHolder {
private SparseArray<View> mViews; // Store ListView item's views
private View item; // Store convertView
private int position; // Cursor
private Context context; // Context
// Constructor, complete initialization
private ViewHolder(Context context, ViewGroup parent, int layoutRes) {
mViews = new SparseArray<>();
this.context = context;
View convertView = LayoutInflater.from(context).inflate(layoutRes, parent, false);
convertView.setTag(this);
item = convertView;
}
// Bind ViewHolder with an item
public static ViewHolder bind(Context context, View convertView, ViewGroup parent,
int layoutRes, int position) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder(context, parent, layoutRes);
} else {
holder = (ViewHolder) convertView.getTag();
holder.item = convertView;
}
holder.position = position;
return holder;
}
@SuppressWarnings("unchecked")
public <T extends View> T getView(int id) {
T t = (T) mViews.get(id);
if (t == null) {
t = (T) item.findViewById(id);
mViews.put(id, t);
}
return t;
}
/**
* Get the current entry
*/
public View getItemView() {
return item;
}
/**
* Get the entry position
*/
public int getItemPosition() {
return position;
}
/**
* Set text
*/
public ViewHolder setText(int id, CharSequence text) {
View view = getView(id);
if (view instanceof TextView) {
((TextView) view).setText(text);
}
return this;
}
/**
* Set image resource
*/
public ViewHolder setImageResource(int id, int drawableRes) {
View view = getView(id);
if (view instanceof ImageView) {
((ImageView) view).setImageResource(drawableRes);
} else {
view.setBackgroundResource(drawableRes);
}
return this;
}
/**
* Set click listener
*/
public ViewHolder setOnClickListener(int id, View.OnClickListener listener) {
getView(id).setOnClickListener(listener);
return this;
}
/**
* Set visibility
*/
public ViewHolder setVisibility(int id, int visible) {
getView(id).setVisibility(visible);
return this;
}
/**
* Set tag
*/
public ViewHolder setTag(int id, Object obj) {
getView(id).setTag(obj);
return this;
}
// Other methods can be expanded by yourself
}
1.0.1 Latest Android Basic Beginner Tutorial Catalog of 2015
1.5.1 Git Tutorial on Basic Operations of Local Repositories
1.8 Project-Related Analysis (Various Files, Resource Access)
[2.5.0 Building a Reusable Custom BaseAdapter
2.5.4 Basic Usage of AutoCompleteTextView (Auto-Complete Text Box)
[2.5.5 Basic Usage of ExpandableListView (Expandable List)](android-tutorial-expand
5.2.4 Fragment Example Tutorial - Bottom Navigation Bar + ViewPager Page Switching
5.2.5 Fragment Example Tutorial - Simple Implementation of News (Shopping) App List Fragment
6.2 Data Storage and Access - SharedPreferences to Save User Preferences
6.3.1 Data Storage and Access - An Introduction to SQLite Database
6.3.2 Data Storage and Access - Another Look at SQLite Database
7.1.1 Android Network Programming Essentials and Http Protocol Learning
8.3.4 Paint API - Detailed Explanation of Xfermode and PorterDuff (I)
8.3.5 Paint API - Detailed Explanation of Xfermode and PorterDuff (II)
8.3.6 Paint API - Detailed Explanation of Xfermode and PorterDuff (III)
8.3.7 Paint API - Detailed Explanation of Xfermode and PorterDuff (IV)
8.3.8 Paint API - Detailed Explanation of Xfermode and PorterDuff (V)
[8.3.10 Paint API - ColorFilter (Color Filter) (
12.4 DrySister Viewing Girls App (First Edition) — 4. Adding Data Caching (Integrate SQLite)