編輯:關於Android編程
我們在開發項目中,listview是最常用的控件,也算是android中控件這塊屬於比較難點的,或容易出現問題的地方,說他難不是說簡單的使用,那個相信大家會,比如結合網絡訪問,異步記載圖片,滑動卡以及嵌套等,今天是寫一篇關於ListView,GridView通用的adapter,而在adapter中getCount,getItem,getItemId,getView要復寫這4個方法,下面看下我們adapter類常寫的方式
布局文件
android:layout_width="match_parent"
android:layout_height="match_parent"
>
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
item布局
android:layout_height="match_parent"
android:orientation="vertical" >
android:layout_width="fill_parent"
android:layout_height="40dp"
/>
MainActivity,class
public class MainActivity extends Activity {
private ListView lv;
private List
private LayoutInflater inflater;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv = (ListView) findViewById(R.id.lv);
inflater = LayoutInflater.from(this);
datas = new ArrayList
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
datas.add("hello world");
MyAdapter adapter = new MyAdapter();
lv.setAdapter(adapter);
}
class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView==null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item, null);
holder.tvContent = (TextView) convertView.findViewById(R.id.tvContent);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tvContent.setText(datas.get(position));
return convertView;
}
}
static class ViewHolder{
TextView tvContent;
}
}
在adapter中我們發現其實adapter真正每次實現不一樣的是getView()方法,我們要對其優化封裝,現在想辦法封裝一個通用的adapter,如何抽取呢?其實無非是java面向對象的幾個基本特征:抽象,封裝,繼承,多態,當我們看見一段代碼在每個類中都會出現,那麼我們就最好把這些相同的代碼封裝到一個父類中,而每個類針對不同的業務方法不一樣,就讓其子類去實現,那麼這個時候我們想到了java中的抽象類了,現在就對adapter方法進行簡單的封裝下:
MyBaseAdapter.java
public abstract class MyBaseAdapter
private List
private Context context;
public MyBaseAdapter(List
super();
this.datas = datas;
this.context = context;
}
@Override
public int getCount() {
return datas.size();
}
@Override
public Object getItem(int position) {
return datas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public abstract View getView(int position, View convertView, ViewGroup parent);
}
我們發現以後只要繼承此MyBaseAdapter就可以少寫getCount,getItem,getItemId。只要復寫getView()方法即可,這比之前優化進了一下步,現在我們看看getView()方法代碼怎麼寫的
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView==null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item, null);
holder.tvContent = (TextView) convertView.findViewById(R.id.tvContent);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.tvContent.setText(datas.get(position));
return convertView;
}
}
static class ViewHolder{
TextView tvContent;
}
現在發現getView方法中與ViewHoler類綁定在一起,我們知道ViewHolder是通過converetView.setTag()與其綁定,這樣當convertView復用時,就不用findViewById了,因為view的id都封裝在ViewHolder中了,所以針對不同的listview,我們肯定要寫不同的ViewHolder類了,那麼現在想打造一個常用的ViewHolder,繼續優化getView方法,
也就是說,實際上們每個convertView會綁定一個ViewHolder對象,這個viewHolder主要用於幫convertView存儲布局中的控件,那麼ViewHolder類一個是提供setTag方法一個是對外提供一個獲取View對象的方法,根據這2點我們寫一個ViewHolder類出來,
public class ViewHolder {
private View convertView;
public void setTag(){
convertView.setTag(this);
}
public View getView(){
return convertView;
}
}
這個ViewHolder肯定是不能用的,convertView這個變量是從來的,一是通過set方法從外界設置進來,二是通過構造函數傳遞進來,但是如果是通過構造函數對convertView進行初始化,那麼我們可以隨便創建ViewHolder對象了,那麼構造函數就不能對外使用了,這個時候我們就把構造函數做成private,所以我們只要對外提供一種方法就是獲取到ViewHoler,而ViewHolder是和convertView綁定的,如果做緩存的都知道,先看看緩存有沒有,如果沒有就去就去new,在方法內部做一個判斷即可,說了這麼多,把剛才的思路轉換成代碼實現如下:
ViewHolder:
public class ViewHolder { private View mConvertView; private ViewHolder(Context context, ViewGroup parent, int layoutId, int position) { mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); 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(); } public View getConvertView() { return mConvertView; } }
@Override public View getView(int position, View convertView, ViewGroup parent) { //實例化一個viewHolder ViewHolder viewHolder = ViewHolder.get(getApplicationContext(), convertView, parent, R.layout.item, position); return viewHolder.getConvertView(); }此時心中一震竊喜,我很牛逼比,運行跑起來界面空白,我的去啊,趕腳好牛逼,怎麼能讓view設置數據到界面上呢,這又是一個廢鬧細胞的時刻到了,心想一個layout那麼多view,怎麼辦啊,神啊,我突然想到了集合的概念,牛比不,抽煙去,等下繼續寫!集合?List能用麼,不可以為什麼呢?因為每個item上的view,是通過id去尋找的,這麼一說我馬上想到了用Map集合,但是我就不用,我使用android一個自帶的容器,叫做SparseArray這個類
public class ViewHolder { private View mConvertView; private final SparseArraymViews; private ViewHolder(Context context, ViewGroup parent, int layoutId, int position) { mViews = new SparseArray (); mConvertView = LayoutInflater.from(context).inflate(layoutId, parent, false); 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(); } public View getConvertView() { return mConvertView; } /** * 通過控件的Id獲取對於的控件,如果沒有則加入views */ public T $(int viewId) { View view = mViews.get(viewId); if (view == null) { view = mConvertView.findViewById(viewId); mViews.put(viewId, view); } return (T) view; } }
class MyAdapter extends MyBaseAdapter
public MyAdapter(List
super(datas, context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//實例化一個viewHolder
ViewHolder viewHolder = ViewHolder.get(getApplicationContext(), convertView, parent,
R.layout.item, position);
TextView tvContent = viewHolder.$(R.id.tvContent);
tvContent.setText(datas.get(position));
return viewHolder.getConvertView();
}
}
}
現在一個adapter中就這幾行代碼了,是不是之前adapter中的代碼要少很多呢,大牛都是寫很少的代碼實現業務,我們在向大牛的方向前行!
LinearLayout是Android中最常用的布局之一,它將自己包含的子元素按照一個方向進行排列。方向有兩種,水平或者豎直。這個方向可以通過設置android:ori
MainActivity.java代碼:package siso.mycrawler;import android.app.Activity;import android
觀察者模式(Observer)觀察者模式是對象的行為模式,又被叫做為模型-視圖模式。這種模式定義了一種一對多的依賴關系,使多個觀察者對象同時監聽某個角色對象。一旦這個角色
相對與視圖動畫 ,屬性動畫(android3.0提出的) 使用條件:完全彌補了View anim System的缺陷,你可以為一個對象的任何屬性添加動畫,(View或者非