Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android開發筆記之適配器

android開發筆記之適配器

編輯:關於Android編程

大家看到這個標題是不是覺得很詫異呢?什麼叫終極適配器,其實就是這種適配器是萬能的,所有需要使用適配器的組件,都可用這一個適配器就行。

既然這樣,就來講講吧。

效果:

這裡寫圖片描述

當然這是個簡單的布局,用普通的適配器也可以實現,這裡只是用它來做個例子,用終極適配器的話,以後你換其他布局,適配器是不用變的,減少了很多代碼。

首先普通的適配器的寫法是:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> public class MyAdapter extends BaseAdapter{ private Context mContext; private List mDatas; private LayoutInflater mLayoutInflater; private int mResId; public MyAdapter(Context context,List data, int resId) { mContext = context; mDatas = data; mLayoutInflater = LayoutInflater.from(mContext); mResId = resId; } @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { Bean bean = mDatas.get(position); ViewHolder holder; if (convertView == null) { convertView= mLayoutInflater.inflate(R.layout.myitem, parent, false); holder = new ViewHolder(); holder.title_Tv = (TextView) convertView.findViewById(R.id.title_Tv); holder.desc_Tv = (TextView) convertView.findViewById(R.id.desc_Tv); holder.time_Tv = (TextView) convertView.findViewById(R.id.time_Tv); holder.phone_Tv = (TextView) convertView.findViewById(R.id.phone_Tv); convertView.setTag(holder); }else { holder = (ViewHolder) convertView.getTag(); } holder.title_Tv.setText(bean.getTitle()); holder.desc_Tv.setText(bean.getDesc()); holder.time_Tv.setText(bean.getTime()); holder.phone_Tv.setText(bean.getPhone()); return convertView; } static class ViewHolder { TextView title_Tv; //標題 TextView desc_Tv; //簡介 TextView time_Tv; //時間 TextView phone_Tv; //電話 } }

制作終極適配器的步驟:

首先我們得分析哪些代碼是不變的,哪些是可變的,這樣才能確定哪些代碼能夠減少。

這三個重寫的方法應該是不變的。

@Override
    public int getCount() {
        return mDatas.size();
    }
    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }
    @Override
    public long getItemId(int position) {
        return position;
    }

還有這些代碼

        ViewHolder holder;
        if (convertView == null) {
            convertView= mLayoutInflater.inflate(R.layout.myitem, parent, false);
            holder = new ViewHolder();
            holder.title_Tv = (TextView) convertView.findViewById(R.id.title_Tv);
            holder.desc_Tv = (TextView) convertView.findViewById(R.id.desc_Tv);
            holder.time_Tv = (TextView) convertView.findViewById(R.id.time_Tv);
            holder.phone_Tv = (TextView) convertView.findViewById(R.id.phone_Tv);
            convertView.setTag(holder);
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

只不過findViewById我們需要處理一下。所以我們應該把這些不變的代碼抽取出來,不應該讓用戶重復寫這些代碼。

把這些代碼抽取出來,當然這些代碼都應該放在ViewHolder中

ViewHolder holder;
        if (convertView == null) {
            convertView= mLayoutInflater.inflate(R.layout.myitem, parent, false);
            holder = new ViewHolder();
        }else {
            holder = (ViewHolder) convertView.getTag();
        }

新建一個類 ViewHolder.java

public class ViewHolder {
    private View mConvertView;
//ViewHolder構造函數,只有當convertView為空的時候才創建
    public ViewHolder(Context context,View convertView, ViewGroup parent, int layouId) {
        convertView = LayoutInflater.from(context).inflate(layouId,parent,false);
        convertView.setTag(this);       //將其setTag()
        mConvertView = convertView;
    }
    //返回一個ViewHolder對象
    public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId) {
        if (convertView == null) {
            return new ViewHolder(context,convertView,parent,layoutId);
        }else {
            return (ViewHolder) convertView.getTag();
        }
    }
}

傳過來的參數包括:Context context, View convertView, ViewGroup parent, int layoutId,這些參數都是加載布局文件所需要的。

然後就是這些代碼需要抽取了:

holder.title_Tv = (TextView) convertView.findViewById(R.id.title_Tv);
            holder.desc_Tv = (TextView) convertView.findViewById(R.id.desc_Tv);
            holder.time_Tv = (TextView) convertView.findViewById(R.id.time_Tv);
            holder.phone_Tv = (TextView) convertView.findViewById(R.id.phone_Tv);

新建方法:

public class ViewHolder {
    //用來存布局中的各個組件,以鍵值對形式
    private SparseArray mViews = new SparseArray<>();
    //返回一個View的子類對象,因為不確定用戶布局有什麼組件,相當於findViewById
    //這裡返回一個泛型,也可以返回一個View或Object
    public T getView(int resId) {
        View view = mViews.get(resId);  //從集合中取出這個組件
        if (view == null) {         //如果為空,說明為第一屏
            view = mConvertView.findViewById(resId);    //從convertView中找
            mViews.put(resId,view);     //再將其以鍵值對存進去
        }
        return (T) view;
    }
}

接下裡的這個返回值就容易了,直接返回就行了

public class ViewHolder {
    /**
     * @return  返回convertView
     */
    public View getConvertView() {
        return mConvertView;
    }
}

這部分工作都完了,就只留下了為組件設置數據的那段代碼了,這段代碼由於是可變的,應該讓用戶來做,所以設置為抽象方法。

新建一個類 CommonAdapter.java 繼承BaseAdapter:

public abstract class CommonAdapter extends BaseAdapter {
    //需要顯示的數據,List中的類型為泛型,因為不知道用戶的封裝Bean
    private List mDatas;
    //上下文
    private Context mContext;
    //布局文件Id
    private int mLayoutId;
    public CommonAdapter(Context context,List data,int layoutId) {
        mDatas = data;
        mContext = context;
        mLayoutId = layoutId;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder.getHolder(mContext,convertView, parent, mLayoutId);
        setDatas(holder,getItem(position));
        return holder.getConvertView();
    }

    /**
     * 為各個item中的控件設置數據
     * @param holder   ViewHolder
     * @param object  從集合中所取的一個對象
     */
    public abstract void setDatas(ViewHolder holder, Object object);
}

到這裡就把剛才那段代碼全部抽取出來了,那再來看一下如何使用吧。

使用步驟:

①添加ListView, 找ListView 這些步驟是一樣的。

②新建一個 Adapter 繼承 CommonAdapter

public class MagicAdapter extends CommonAdapter {
    public MagicAdapter(Context context, List data, int layoutId) {
        super(context, data, layoutId);
    }
    @Override
    public void setDatas(ViewHolder holder, Object object) {
        Bean bean = (Bean) object;
        ((TextView)holder.getView(R.id.title_Tv)).setText(bean.getTitle());
        ((TextView)holder.getView(R.id.desc_Tv)).setText(bean.getDesc());
        ((TextView)holder.getView(R.id.time_Tv)).setText(bean.getTime());
        ((TextView)holder.getView(R.id.phone_Tv)).setText(bean.getPhone());
    }
}

注:

這裡寫圖片描述

③為ListView設置適配器

//為listView設置適配器
        mListView.setAdapter(new MagicAdapter(this,mDatas,R.layout.listview_item));

到這裡就實現了萬能的適配器了,是不是減少了很多代碼。我們知道java三大特性是封裝、繼承、多態。這篇例子可以鍛煉一下大家的封裝能力。大家試試吧

核心代碼:

activity_main.xml




    

listview_item.xml



    
    
    
    

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ListView mListView;
    private List mDatas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();
        //為listView設置適配器
        mListView.setAdapter(new MagicAdapter(this,mDatas,R.layout.listview_item));
    }

    /**
     * 初始化組件
     */
    private void initView() {
        mListView = (ListView) findViewById(R.id.listView);
    }

    /**
     * 初始化數據
     */
    private void initData() {
        mDatas = new ArrayList<>();
        //模擬數據
        for (int i=0; i < 6; i++) {
            Bean bean = new Bean("新技能" +i,"打造萬能適配器"+ i,"2016-5-22","10086");
            mDatas.add(bean);
        }
    }
}

ViewHolder.java

public class ViewHolder {
    private View mConvertView;
    //用來存布局中的各個組件,以鍵值對形式
    private SparseArray mViews = new SparseArray<>();
    //ViewHolder構造函數,只有當convertView為空的時候才創建
    public ViewHolder(Context context,View convertView, ViewGroup parent, int layouId) {
        convertView = LayoutInflater.from(context).inflate(layouId,parent,false);
        convertView.setTag(this);       //將其setTag()
        mConvertView = convertView;
    }
    //返回一個ViewHolder對象
    public static ViewHolder getHolder(Context context, View convertView, ViewGroup parent, int layoutId) {
        if (convertView == null) {
            return new ViewHolder(context,convertView,parent,layoutId);
        }else {
            return (ViewHolder) convertView.getTag();
        }
    }
    //返回一個View的子類對象,因為不確定用戶布局有什麼組件,相當於findViewById
    //這裡返回一個泛型,也可以返回一個View或Object
    public T getView(int resId) {
        View view = mViews.get(resId);  //從集合中取出這個組件
        if (view == null) {         //如果為空,說明為第一屏
            view = mConvertView.findViewById(resId);    //從convertView中找
            mViews.put(resId,view);     //再將其以鍵值對存進去
        }
        return (T) view;
    }

    /**
     * @return  返回convertView
     */
    public View getConvertView() {
        return mConvertView;
    }

}

CommonAdapter.java

public abstract class CommonAdapter extends BaseAdapter {
    //需要顯示的數據,List中的類型為泛型,因為不知道用戶的封裝Bean
    private List mDatas;
    //上下文
    private Context mContext;
    //布局文件Id
    private int mLayoutId;
    public CommonAdapter(Context context,List data,int layoutId) {
        mDatas = data;
        mContext = context;
        mLayoutId = layoutId;
    }
    @Override
    public int getCount() {
        return mDatas.size();
    }

    @Override
    public Object getItem(int position) {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder.getHolder(mContext,convertView, parent, mLayoutId);
        setDatas(holder,getItem(position));
        return holder.getConvertView();
    }

    /**
     * 為各個item中的控件設置數據
     * @param holder   ViewHolder
     * @param object  從集合中所取的一個對象
     */
    public abstract void setDatas(ViewHolder holder, Object object);
}

Bean.java

public class Bean {
    private String title;       //標題
    private String desc;        //簡介
    private String time;        //時間
    private String phone;       //電話

    public Bean(String title, String desc, String time, String phone) {
        this.title = title;
        this.desc = desc;
        this.time = time;
        this.phone = phone;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

MagicAdapter.java

public class MagicAdapter extends CommonAdapter {
    public MagicAdapter(Context context, List data, int layoutId) {
        super(context, data, layoutId);
    }
    @Override
    public void setDatas(ViewHolder holder, Object object) {
        Bean bean = (Bean) object;
        ((TextView)holder.getView(R.id.title_Tv)).setText(bean.getTitle());
        ((TextView)holder.getView(R.id.desc_Tv)).setText(bean.getDesc());
        ((TextView)holder.getView(R.id.time_Tv)).setText(bean.getTime());
        ((TextView)holder.getView(R.id.phone_Tv)).setText(bean.getPhone());
    }
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved