您好,登錄后才能下訂單哦!
這篇文章給大家介紹ListView中怎么使用泛型適配器,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
1.先創建好我們今天需要的控件、源數據以及Bean類。
控件只有一個ListView
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activities.MainActivity"> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/mlv"/> </LinearLayout>
beans方法模擬了一個假數據
private void beans() { list = new ArrayList<>(); for (int i = 0; i < 16; i += 4) { list.add(new Student("同學" + i, "男", 15 + i, R.drawable.a, true)); list.add(new Student("同學" + (i + 1), "男", 15 + i, R.drawable.b, false)); list.add(new Student("同學" + (i + 2), "男", 15 + i, R.drawable.c, false)); list.add(new Student("同學" + (i + 3), "男", 15 + i, R.drawable.d, true)); } }
這是bean類
package zy.pers.homework_20.bean; public class Student { private String name; private String sex; private int age; private int imgId; private boolean isOver; public Student(String name, String sex, int age, int imgId,boolean isOver) { this.name = name; this.sex = sex; this.age = age; this.imgId = imgId; this.isOver = isOver; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getImgId() { return imgId; } public void setImgId(int imgId) { this.imgId = imgId; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", sex='" + sex + '\'' + ", age=" + age + ", imgId=" + imgId + '}'; } public boolean isOver() { return isOver; } public void setOver(boolean over) { isOver = over; } }
2.創建MyBaseAdapter繼承BaseAdapter
public class MyBaseAdapter<T> extends BaseAdapter { @Override public int getCount() { return 0; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { return null; } }
3.我們說通用適配器傳入布局id和源數據,所以我們定義這兩個量接收傳入的數據。
private List<Student> list; private int mLayRes; public MyBaseAdapter(List<Student> list, int mLayRes) { this.list= list; this.mLayRes = mLayRes; }
4.重寫我們的前三個方法
前三個方法應該算是比較簡單的了,
@Override public int getCount() { return list != null ? list.size() : 0; } @Override public T getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; }
第一個一個簡單的判斷,返回list的大小。第二個跟第三個和以前適配器一樣,只是getItem的返回值寫成了泛型。
5.寫Viewholder類,這個是很麻煩的,我們先創建出來Viewholder,之后的方法我們一步一步添加。
public static class ViewHolder { private SparseArray<View> mViews = new SparseArray<>(); private Context mContext; private int position; private int layRes; private View itemView;
private ViewHolder(Context context, ViewGroup parent, int layRes) { this.mContext = context; this.layRes= layRes; this.itemView = LayoutInflater.from(context).inflate(layRes, parent, false); this.itemView.setTag(this); }
public static ViewHolder bind(int position, View convertView, ViewGroup parent, int layRes, Context context) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(context, parent, layRes); } else { holder = (ViewHolder) convertView.getTag(); holder.itemView = convertView; } holder.position = position; return holder; }
東西有點多,我們順著邏輯慢慢看:
1)首先是通過單例來實現,所以我們需要一個私有化構造方法,里面有三個參數,分別是上下文,ViewGroup和布局id,這三個屬性是我們必須要用到的,我們傳入上下文獲取inflater,把布局id傳進去,然后把holder傳入我們的itemView中。
這一步我們應該比較熟悉吧,我們以前是在getView中實現這一步的。
2)然后我們看下面的bind方法,他的參數有五個。其實有三個參數我們很熟悉,就是我們getView中的三個參數。在這基礎上我們又添加了兩個參數,布局id和上下文。
然后為了優化我們先判斷當前的convertView是否為空,如果為空就新建一個Viewholder,讓convertView在私有構造器中加載;如果不為空,直接通過getTag拿到。
注意我們要對holder中的兩個參數進行修改,一個是itemView,一個是position。因為我們優化過后,如果convertView不為空,他里面是有之前的數據的,其他的幾個屬性我們不用管,但是這兩個還是儲存著上一個的內容。我們需要讓他重新指向當前的convertView和position,給大家畫一張圖就很明白了:
索引什么的畫的可能不準確,但是主要就是這么個意思,大家領會精神哈。
最后返回holder。
3)我們還需要返回我們加載完成的convertView,
public View getItemView() { return itemView; }
現在我們Viewholder基本框架寫完了,我們暫時不管他了,去寫getView。
6.重寫方法getView:
我們剛才說了,在adapter中寫一個抽象方法,然后通過回調方法,實現多類型適配,也就是說這個抽象方法是寫我們給具體控件添加數據的,我們在這里面傳遞兩個參數,一個是我們的Viewholder,另一個是對應位置的數據,類型為泛型。
public abstract void bindView(ViewHolder holder,T obj);
因為我們出現了抽象方法,所以我們的MyBaseAdapter需要變成抽象類,
public abstract class MyBaseAdapter<T> extends BaseAdapter {
這是我們的getView
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.bind(position,convertView,parent,mLayRes,parent.getContext()); bindView(holder,list.get(position)); return holder.getItemView(); }
現在我們的適配器已經完成百分之九十了,還差一點,我們需要寫幾個輔助方法,為了方便我們等會進行適配。
1.獲取指定控件
public <T extends View> T getView(int id){ T t = (T) mViews.get(id); if(t == null){ t = itemView.findViewById(id); mViews.put(id,t); } return t; }
在Viewholder中寫一個getView方法,通過控件id來獲取指定控件。
2.TextView控件輸入數據
public ViewHolder setText(int id,CharSequence text){ View view = getView(id); if(view instanceof View){ ((TextView)view).setText(text); } return this; }
3.ImageView輸入圖片
public ViewHolder setImg(int id,int resId){ View view = getView(id); if(view instanceof View){ ((ImageView)view).setImageResource(resId); }else view.setBackgroundResource(resId); return this; }
4.復選框輸入選定狀態
public ViewHolder setCheckable(int id,boolean checkable){ View view = getView(id); if(view instanceof View){ ((CheckBox)view).setChecked(checkable); } return this; }
好啦,先在我們的適配器完全寫完了,我們來看一下效果吧。
private void initTools() { ListView mLv = (ListView) findViewById(R.id.mlv); adapter = new MyBaseAdapter<Student>(list,R.layout.item_one) { @Override public void bindView(ViewHolder holder, Student obj) { holder.setText(R.id.name,obj.getName()) .setText(R.id.age,obj.getAge() + "") .setText(R.id.sex,obj.getSex()) .setImg(R.id.head,obj.getImgId()) .setCheckable(R.id.mc,obj.isOver()); } }; mLv.setAdapter(adapter); }
關于ListView中怎么使用泛型適配器就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。