鴻神出品,必屬精品,這個就 NB 了,地址在這裡,自從看了這個後,我後面的 Android 專案幾乎都是採用這樣的模式,媽媽再也不用擔心我重複的寫 ListView 的 Adapter了,另外加上了點選事件
CommonAdapter 傳入一個泛型 T 以供裝載不同的 Bean 物件,同時暴露一個 convert 方法,並且還把 viewHolder 和本 Item對於的 Bean 物件給傳出去,外部類實現 convert 方法後,通過 ViewHolder 把View 找到,通過 Item 設定值,這裡傳入一個 postion 是為了方便做事件監聽
public abstract class CommonAdapter<T> extends BaseAdapter {
private List<T> mData;
private Context mContext;
protected final int mLayoutId;
public CommonAdapter(Context mContext, List<T> mData, int mLayoutId) {
this.mData = mData;
this.mContext = mContext;
this.mLayoutId = mLayoutId;
}
@Override
public int getCount() {
return mData.size()!=0?mData.size():0;
}
@Override
public T getItem(int position) {
return mData.get(position)!=null?mData.get(position):null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = ViewHolder.get(mContext, convertView, parent, mLayoutId, position);
convert(viewHolder,getItem(position),position);
return viewHolder.getConvertView();
}
//對外公佈了一個convert方法,並且還把viewHolder和本Item對於的Bean物件給傳出去,
// 實現convert方法後,裡面需要幹嘛呢?通過ViewHolder把View找到,通過Item設定值
//傳入一個postion方便做事件監聽
public abstract void convert(ViewHolder holder,T item, int position);
}
複製程式碼
ViewHolder 用來實現裝載佈局,儲存 View,並與 convertview 繫結
public class ViewHolder {
//與傳統的ViewHolder不同,
// 我們使用了一個SparseArray<View>用於儲存與之對於的convertView的所有的控制元件,
// 當需要拿這些控制元件時,通過getView(id)進行獲取;
private final SparseArray<View> mViews;
private View mConvertView;
private int mPosition;
public ViewHolder(Context context,ViewGroup parent,int layoutId,int position) {
this.mViews = new SparseArray<>();
this.mConvertView = LayoutInflater.from(context).inflate(layoutId,parent,false);
this.mPosition = position;
mConvertView.setTag(this);
}
//拿到一個ViewHolder物件
public static ViewHolder get(Context context, View convertView,ViewGroup parent, int layoutId, int position) {
if (convertView == null) {
return new ViewHolder(context,parent,layoutId,position);
}
return (ViewHolder)convertView.getTag();
}
//通過控制元件的Id獲取對於的控制元件,如果沒有則加入views
public <T extends View> T getView(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = mConvertView.findViewById(viewId);
mViews.put(viewId,view);
}
return (T) view;
}
public View getConvertView() {
return mConvertView;
}
/**
* 為TextView設定字串
* @param viewId
* @param text
* @return
*/
public ViewHolder setText(int viewId, String text){
TextView textView = getView(viewId);
textView.setText(text);
return this;
}
/**
* 為ImageView設定圖片
*
* @param viewId
* @param drawableId
* @return
*/
public ViewHolder setImageResource(int viewId, int drawableId){
ImageView imageView = getView(viewId);
imageView.setImageResource(drawableId);
return this;
}
/**
* 為ImageView設定圖片
* @param viewId
* @param bm
* @return
*/
public ViewHolder setImageBitmap(int viewId, Bitmap bm){
ImageView imageView = getView(viewId);
imageView.setImageBitmap(bm);
return this;
}
public ViewHolder setImageByUrl(int viewId, String url){
//使用url載入圖片
return this;
}
//返回一個Postion
public int getPosition(){
return mPosition;
}
}
複製程式碼
再來看看封裝 Adpater 後 MainActivity 的寫法
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private List<String> simpleData = Arrays.asList("aaa", "bbb", "ccc", "ddd", "Ffff",
"ggg", "111", "222", "333", "$44", "5555", "666", "777", "8888", "bbb", "ccc", "ddd", "Ffff");
private List<BeanItem> mData = Arrays.asList(
new BeanItem("保險","支付寶推出大病無憂保,看來馬雲把觸角伸到保險領域了,每線下消費一筆","11111111",android.R.drawable.ic_delete),
new BeanItem("重疾險","健康保障金額就會增加,最高上限是2000,這個是免費給你的","22222222",android.R.drawable.ic_delete),
new BeanItem("Kotlin","今天開啟微信,幾乎各個技術公眾號都在寫 Google IO 2017 的訊息","33333333",R.mipmap.ic_launcher),
new BeanItem("XXX","XXXXXXXXXXXXXXXX,在食XXXX三樓","44444444",R.mipmap.ic_launcher),
new BeanItem("XXXX","週三早XXXX上撿到XXX一隻XXX","1ASFASDF11",android.R.drawable.ic_delete)
);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView mListView = (ListView) findViewById(R.id.listView);
//通用寫法
// mListView.setAdapter(new MyAdater(this,mData));
//封裝後寫法(簡單佈局)
// mListView.setAdapter(new CommonAdapter<String>(getApplicationContext(), simpleData, R.layout.list_item) {
// @Override
// public void convert(final ViewHolder holder, String item) {
// holder.setText(R.id.textView, item);
// //新增點選事件
// holder.getView(R.id.textView).setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// int position = holder.getPosition();
// Toast.makeText(MainActivity.this, "點選了第: "+position+"個條目", Toast.LENGTH_SHORT).show();
// }
// });
// }
// });
//封裝後寫法(複雜佈局)
mListView.setAdapter(new CommonAdapter<BeanItem>(getApplicationContext(),mData,R.layout.list_item) {
@Override
public void convert(ViewHolder holder, BeanItem item, final int position) {
holder.setText(R.id.tv_title,item.getTitle());
holder.setText(R.id.tv_describe,item.getDesc());
holder.setText(R.id.tv_time,item.getTime());
holder.setImageResource(R.id.image,item.getImageId());
holder.getView(R.id.relativeLayout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "點選sf了sf第: "+position+"個條目", Toast.LENGTH_SHORT).show();
}
});
}
});
}
}
複製程式碼
list_item 佈局是這樣的
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ffffff"
android:id="@+id/relativeLayout"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="星期天"
android:textSize="16sp"
android:textColor="#444444" />
<TextView
android:id="@+id/tv_describe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv_title"
android:layout_marginTop="10dp"
android:maxLines="2"
android:minLines="1"
android:text="2017年5月21日09:36:27"
android:textColor="#898989"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_describe"
android:layout_marginTop="10dp"
android:text="20130240122"
android:textColor="#898989"
android:textSize="12sp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/image"
android:layout_centerInParent="true"
android:layout_alignParentRight="true"
android:src="@mipmap/ic_launcher"/>
</RelativeLayout>
複製程式碼
效果和之前寫的還是一樣的,哈哈!