建立一個可重複使用的自訂BaseAdapter


本節引言:

如題,本節帶給大家的是建構一個可重複使用的自訂BaseAdapter,我們每每涉及到ListView GridView等其他的Adapter控件,都需要自己另外寫一個BaseAdapter類,這樣顯得非常麻煩, 又例如,我們想在一個介面顯示兩個ListView的話,我們也是需要些兩個BaseAdapter... 這,程式設計師都是喜歡偷懶的哈,這節我們就來寫一個可重複使用的自訂BaseAdapter類別~


1.我們一點點開始改:

首先我們把上節寫的自訂BaseAdapter貼下,等下我們就要對他進行升級改造

/**
 * 由 Jay 創立於 2015 年 9 月 21 日 0021。 */
public 類別 MyAdapter 擴充 BaseAdapter{

私有 Context mContext;
私有 LinkedList; mData;

    public MyAdapter() {
#    }

    public MyAdapter(LinkedList mData         this. mContext = mContext;
    }

    @Override
    public int getCount() {
   @Override
public Object getItem(int position) {
        return null;
    }

      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());#. View.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
            con.     holder = (ViewHolder) convertView.getTag();
        }
        holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
        return convertView;
    }
##  
        if (mData == null) {
            mData ) mData.add(data);
        notifyDataSetChanged();
    }

    //往特定位置,新增一個元素
    public void add(int position,Data data){
        new LinkedList<>( );
        }
        mData.add(position, data);
         data) {
        if(mData ! = null) {
            mData.remove(data);
        }
   void remove(int position) {
        if(mData ! = null) {
            mData.remove(position);
        }
   public void clear() {
        if(mData != null ) {
            mData.clear();
        }
     ViewHolder {
        ImageView img_icon;
        TextView txt_content;
    }

}

#

升級1:將Entity設定成泛型

好的,畢竟我們傳遞過來的Entitiy實體類別可能千奇百怪,例如有Person,Book,Wether等,所以我們 將Entity設定成泛型,修改後的程式碼如下:

<pre>
public 類別 MyAdapter<T> 擴充 BaseAdapter {

    私有 Context mContext;
    私有 LinkedList; mData;

    public MyAdapter() {
#    }

    public MyAdapter(LinkedList mData         this. mContext = mContext;
    }

    @Override
    public int getCount() {
   @Override
public Object getItem(int position) {
        return null;
    }

      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());#. View.findViewById(R.id.img_icon);
holder.txt_content = (TextView) convertView.findViewById(R.id.txt_content);
            con.     holder = (ViewHolder) convertView.getTag();
        }
        holder.img_icon.setImageResource(mData.get(position).getImgId());
holder.txt_content.setText(mData.get(position).getContent());
        return convertView;
    }
##  
        if (mData == null) {
            mData ) mData.add(data);
        notifyDataSetChanged();
    }

    //往特定位置,新增一個元素
    public void add(int position,T data){
        new LinkedList<>( );
        }
        mData.add(position, data);
         data) {
        if(mData ! = null) {
            mData.remove(data);
        }
   void remove(int position) {
        if(mData ! = null) {
            mData.remove(position);
        }
   public void clear() {
        if(mData != null ) {
            mData.clear();
        }
     ViewHolder {
        ImageView img_icon;
        TextView txt_content;
    }

}

#

好的,上面我們做的事只是將Data類型換成了泛型T!


升級2:ViewHolder類別的升級改造:

我們先來看看前面我們的ViewHolder做了什麼? 答:findViewById,設定控制項狀態; 下面我們要在完成這個基礎上,將getView()方法大部分的邏輯寫到ViewHolder類別裡, 這個ViewHolder要做的事:

  • 定義一個尋找控制項的方法,我們的想法是透過揭露公共的方法,當呼叫方法時傳遞過來 控制項id,以及設定的內容,例如TextView設定文字: public ViewHolder setText(int id, CharSequence text){文字設定}
  • 將convertView重複使用部分搬到這裡,那就需要傳遞一個context物件了,我們把需要取得 的部分都寫到構造方法中!
  • 寫一堆設定方法(public),例如設定文字大小顏色,圖片背景等!

好的,接下來我們就來一步步改造我們的ViewHolder類別


1)相關參數與建構方法:

#public static class ViewHolder {

    private SparseArray<View> mViews;   //儲存ListView 的        //存放convertView
#    private int position;               ///遊標
    private Context context;            //Context上下文

    /建構法outRes) {
        mViews = new SparseArray< >();
        this.context = context;
        View convertView = Lay View.setTag(this);
        item = convertView;
    }

#    ImageView img_icon;
    TextView txt_content;
#}

    TextView txt_content;
#}

2)綁定ViewHolder與Item

在上面的基礎上我們再加入一個綁定的方法

//綁定ViewHolder與item
public static ViewHolder bind(Context context, View convertView, ViewGroup parent,
            {
    ViewHolder holder;
    if(convertView == null) {
        holder context, parent, layoutRes);
    } else {
        holder = (ViewHolder) convert 
    holder.position = position;
    return holder;
}

3)根據id取得集合中儲存的控制項

public <T extends View> T getView( int id) {
    T t = (T) mViews.get(id);
    if(t == null) {
     mViews .put(id, t);
    }
    return t;
}

#

4) 接下來我們再定義一個公開出來的方法

/**
 * 取得目前條目
 */
public View getItemView() {
    return item;
}

/**
 * 取得條目位置
 */
public int getItemPosition() {
    返回位置;
}

/**
 * 設定文字
 */
public ViewHolder setText(int id, CharSequence text) {
    View view = getView(id);
    if(view instanceof TextView)  . #    }
    返回此;
}

/**
 * 設定圖片
 */
public ViewHolder setImageResource(int id, int drawableRes) {
  ;
    if(view instanceof ImageView) {
        ((ImageView) view).setImageResource(drawableRes );#c drawableRes);
    }
    return this;
}


#/**
 * 設定點選監聽
 */
public ViewHolder setOnClickListener(int id, View.OnClickListenerlistener) {
    getView(id).setOnClickListener (listener ) );
    回傳此;
}

/**
 * 設定可見
 */
public ViewHolder setVisibility(int id, int visible) {
    getView(id).setVisibility (可見);
    返回此;
}

/**
 * 設定標籤
 */
public ViewHolder setTag(int id, Object obj) {
    getView(id). setTag (obj);
    return this;
}

#//其他方法可自行擴展

好的,ViewHolder的改造升級完成~


升級3:定義一個抽象方法,完成ViewHolder與Data資料集的綁定

public abstract void bindView(ViewHolder holder, T obj);

我們建立新的BaseAdapter的時候,實作這個方法就好,另外,別忘了把我們自訂 的BaseAdapter改成abstact抽象的!


升級4:修改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.升級完畢,我們寫程式碼來體驗下:

我們要實現的效果圖:

1.png

就是上面有兩個列表,佈局不一樣,但我只使用一個BaseAdapter類別來完成上述效果!

關鍵程式碼如下:

MainActivity.java

公共類別MainActivity擴充AppCompatActivity{

#私有Context mContext;
    私有ListView list_book;
    私有ListView list_app;##  myAdapter1 = null;
    private MyAdapter; myAdapter2 = null;
    私有清單; mData1 = null;
    私人清單<圖書>; mData2 = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {##  ); setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        init();

    }

    private void init( );
        list_app = (ListView) findViewById(R.id.list_app);

        /      mData1.add(new App( R.mipmap.iv_icon_baidu,"百度"));
        mData1.add(new App(R.mipmap.iv_icon_douban,"豆瓣"));
  . "支付寶"));

        mData2 = new ArrayList();
        mData2.add(new Android("《第一行程式碼郭氏》","閔 mData2.add(new Android("《第一行程式碼郭氏》","閔 mData2.add(new Android("《第一行程式碼郭葉》","閔 mData2.add(new Android("《第一行程式碼郭》","閔 mData2.add(new Android("《第一行程式碼郭》","閩號" ##        mData2.add(new Book("《Android群英傳》","徐宜生"));
        mData2.add(new Book("《Android工作藝術》」,"任玉剛探索》","任玉剛探索」,"。
##        //適配器初始化
        myAdapter1 = new MyAdapter((ArrayList)m            public void bindView(ViewHolderholder, App obj) {
#                holder.setImageRe    holder.setText(R.id.txt_aname,obj.getaName()) ;
            }
#        };
        my),       @Override
            public void bindView(ViewHolder holder,書籍物件) {
                holder.setText(R.id.txt_bname,obj.getbName());
      
            }
#        } ;

        //ListView設定下Adapter:
        list_book.setAdapter(myAdapter2);
   
# }

我們寫的可重複使用的BaseAdapter的使用就如上面所述~


3.程式碼範例下載:

ListViewDemo4.zip

貼下最後寫好的MyAdapter類別吧,可以依照自己的需求擴充:

MyAdapter.java

/**
 * 由 Jay 創立於 2015 年 9 月 22 日 0022。 */
公共抽象類別MyAdapter 擴充 BaseAdapter {

    私有 ArrayList; mData;
    private int mLayoutRes;           // 佈局id


    public MyAdapter() {
    }

    public MyAdapter(ArrayList mData, int mLayoutRes) {
        this.mData = mData;
        this.mLayoutRes = mLayoutRes;
    }
##    @Override
    ? mData.size() : 0;
    }

#    @Override
    public T getItem(int position) ##    @Override
    public long getItemId(int position) {
        return position;# position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder.bind(parent.getContext(), convertView, parent, mLayoutRes
  bindView(holder, getItem(position));
        return holder.getItemView() ;
    }

    public abstract    public abstract void bindView(ViewHolder holder, T obj) -c## ## if ( mData == null) {
            mData = new ArrayList<>();
          notifyDataSetChanged();
    }

    //往特定位置,新增一個元素
    public void add(int position, T data) {
    mData = new ArrayList<> ;();
        }
        mData.add(position, data);
        data) {
        if ( mData != null) {
            mData.remove(data);
        }#    public void remove(int position) {
        if ( mData != null) {
            mData.remove(position);
        )   public void clear() {
#        if (mData ! = null) {
           mData.clear();
        }
     static 類 ViewHolder {

        private SparseArray< ;查看> mViews;   // 儲存ListView的item中的View
        private View item;                  // 蹲convertView
        private int position;               //遊標
        private Context context;            //情境情境

        //建構方法,完成相關初始化
        private ViewHolder(Context context, ViewGroupparent, intlayoutRes) {
            mViews = new SparseArray          View convertView = LayoutInflater.from(context).inflate( layoutRes, parent, false);
            con.   //綁定ViewHolder與item
        public static ViewHolder bind(Context context, View convertView, ViewGroup parent,
                                      int layoutRes, int position) {
            ViewHolderholder;
            if (convertView == null) {
                holder = new ViewHolder(context, parent, layoutRes);
} else {
                holder = (ViewHolder) convertView.getTag(();
  0;>         }
            holder.position =地點;
        }

        @SuppressWarnings("unchecked")
        public ; T getView(int id) {
            T t = (T) mViews.get(id);
            if (t == null) {
                t = (T) item.findViewById            }
            return t;
      

##        /**
         * 以取得目前條目
         */
        public View getItemView() {
          /**
         * 取得條目位置
         */
        public int getItemPosition() {
            返回位置;
        public ViewHolder setText(int id, CharSequence text) {
            以檢視view = getView(id);
            if (view instanceof TextView) {
          }
            所回復中;
        }

#        }

#        /**
         * 設定文字
         */
        public ViewHolder setImageResource(int id, int drawableView;##view            if (view instanceof ImageView) {
                ((ImageView) view).setIm               view.setBackgroundResource(drawableRes);
            #        }


        /**
         * 設定點選監聽
         */


#        /**
         * 設定可見
         */
        public      getView(id).setOnClickListener(listener);
            返回此;
        }

        {
            getView(id).setVisibility(visible);
            return this;
        }

#     j) {
            getView(id).setTag(obj);
            return this;
        }

#        //使用其他方法與其他方法111

#o##

本節小結:

本節為大家介紹如何來實現一個可供復用的BaseAdapter,當然大家可以在這個的基礎上根據 自己的需求進行修改,例如透過非同步設定網路圖片等~改程式碼是參考鴻洋大神的影片寫的: 影片連結:Android-打造萬用適配器另外,實際編寫遇到一些問題,非常感謝Berial(B神)的耐心點撥~2.jpgありがとうございます~