編輯:關於Android編程
通過前面的優化布局之後,我們接著來講如何打造一個通用的適配器,那麼通用適配器能干嗎呢?很簡單,減少我們對代碼的書寫,下面開始上代碼了。
MyAdapter.java
public class MyAdapter extends BaseAdapter { private List<Student> data; public MyAdapter(List<Student> data) { this.data = data; } @Override public int getCount() { return data == null ? 0 : data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } /** * * @param position * @param convertView * @param parent * @return */ @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ //解析布局 convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,null); //創建ViewHolder持有類 holder = new ViewHolder(); //將每個控件的對象保存到持有類中 holder.tvName = (TextView)convertView.findViewById(R.id.mTv1); holder.tvSex = (TextView)convertView.findViewById(R.id.mTv2); //將每個convertView對象中設置這個持有類對象 convertView.setTag(holder); } //每次需要使用的時候都會拿到這個持有類 holder = (ViewHolder)convertView.getTag(); //然後可以直接使用這個類中的控件,對控件進行操作,而不用重復去findViewById了 holder.tvName.setText(data.get(position).getName()); holder.tvSex.setText(data.get(position).getSex()); return convertView; } /** * 通過這個類來保存當前所有的控件id */ static class ViewHolder{ TextView tvName; TextView tvSex; } }
在上面的代碼中,我們先看看有哪些代碼的格式或形式都是重復在使用的,首先不難看出,public int getCount() 、public long getItemId(int position) 、public long getItemId(int position)這三個方法是不是每次都要實現呢,由此我們可以先將這些代碼提取出來,放到MyBaseAdapter中,由於我們每次的重要部分是實現getView方法,所以這個方法我們不需要在這裡面寫,直接將MyBaseAdapter設置為抽象類就可以了,然需要實現getView的類來繼承他即可,因此MyAdapter可以繼承MyBaseAdapter然後實現getView方法即可
MyBaseAdapter.java
public abstract class MyBaseAdapter extends BaseAdapter { protected List<Student> data; public MyBaseAdapter(List<Student> data){ this.data = data; } @Override public int getCount() { return data == null ? 0 : data.size(); } @Override public Object getItem(int position) { return data.get(position); } @Override public long getItemId(int position) { return position; } }
MyAdapter.java
public class MyAdapter extends MyBaseAdapter { public MyAdapter(List<Student> data) { super(data); this.data = data; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView == null){ convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,null); holder = new ViewHolder(); holder.tvName = (TextView)convertView.findViewById(R.id.mTv1); holder.tvSex = (TextView)convertView.findViewById(R.id.mTv2); convertView.setTag(holder); } holder = (ViewHolder)convertView.getTag(); holder.tvName.setText(data.get(position).getName()); holder.tvSex.setText(data.get(position).getSex()); return convertView; } static class ViewHolder{ TextView tvName; TextView tvSex; } }
這樣,每次自定義只需要繼承MyBaseAdapter就可以了,不過還是那句話,沒有最優,只有更優,所以我們還要接著優化,接著封裝,那麼我們接著從上面的getView方法中看,還有哪些代碼是我們經常重復使用到的代碼呢?其實你會發現每次我們都需要操作相同的這段代碼:
ViewHolder holder = null; if(convertView == null){ convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,null); holder = new ViewHolder(); holder.tvName = (TextView)convertView.findViewById(R.id.mTv1); holder.tvSex = (TextView)convertView.findViewById(R.id.mTv2); convertView.setTag(holder); } holder = (ViewHolder)convertView.getTag(); holder.tvName.setText(data.get(position).getName()); holder.tvSex.setText(data.get(position).getSex()); return convertView; }
我們可以先再次理解下這段代碼,首先我們每次都要創建一個holder持有者對象,設置到對應的converView的setTag中,然後,每次要拿到hoder對象,對hoder對象中的控件進行操作,對於上面的代碼我們可以直接將他簡化為以下幾個步奏
1.ViewHolder holder = 拿到holder //每次拿到對應的holder對象即可
2.TextView tv = holder.getView() //拿到每個控件對應的id
3. tv.setText() //對控件進行操作
4. return view //返回view即可
下面開始寫一個通用的ViewHolder通用類,來優化我們的實現,代碼如下:
ViewHolder.java
public class ViewHolder { //被點擊的當前位置 private int position; //用一個map集合來保存每個控件的id,這個SparseArray是android提供的一個比map使用效率更高的一個 //集合,但是局限是,key只能是int類型,所以當鍵值對涉及到key是int類型時,可以優先考慮使用這個集合 private SparseArray<View> array; //復用的布局 private View convertView; //上下文 private Context context; //解析的布局資源id private int layout; public ViewHolder(){ } //帶三個構造的方法,這裡將構造方法私有,防止外界去創建,通過自身的靜態方法去創建對象即可 private ViewHolder(ViewGroup parent,int position,int layout){ this.position = position; this.context = parent.getContext(); //每次創建對象,就將布局解析出來 convertView = LayoutInflater.from(parent.getContext()).inflate(layout,null); //然後將對象保存到convertView對應的setTag中,方便每次該獲取 convertView.setTag(this); array = new SparseArray<>(); } //通過這個方法,可以創建ViewHolder對象 public static ViewHolder getHolder(View convertView, ViewGroup parent, int position,int layout){ //每次判斷converView是否為空,如果為空就直接返回這個創建的對象 if(convertView == null){ return new ViewHolder(parent,position,layout); }else{ //不為空的情況,就跟我們上面的代碼一樣,每次通過復用的控件拿到對應的ViewHolder對象 ViewHolder holder = (ViewHolder)convertView.getTag(); //這裡一定要更新下下標的位置,雖然對象相同,但是我們每次都要更新現有的位置, holder.position = position; //返回已經創建好的holder對象 return holder; } } /** * 這個方法是通過控件id拿到對應的控件 */ public <T extends View> T getView(int viewId){ //每次通過viewId鍵去拿到到對應的控件 View view = array.get(viewId); //如果為空,表示該集合中還沒有存入該控件 if(view == null){ //先要去通過converView拿到控件id view = convertView.findViewById(viewId); //保存到集合中,以便下次直接獲取 array.put(viewId,view); } //返回View的子類控件,采用泛型的方便是不需要強制轉換了 return (T)view; } //得到converView布局 public View getConvertView(){ return convertView; }
通過上面的代碼我們就已經封裝好了一個通用的ViewHolder類了,下面我們的MyAdapter.java則可以更加簡單的只寫一下代碼了:
public class MyAdapter extends MyBaseAdapter { public MyAdapter(List<Student> data) { super(data); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = ViewHolder.getHolder(convertView,parent,position, R.layout.list_item); TextView tvName = holder.getView(R.id.mTv1); TextView tvSex = holder.getView(R.id.mTv2); tvName.setText(data.get(position).getName()); tvSex.setText(data.get(position).getSex()); return holder.getConvertView(); } }
好了,上面的代碼是不更簡單了呢,其實我們這裡只是封裝了ViewHolder類哦,還有更通用的等著我們去封裝呢,下次我們需要封裝的就是如何把getView中的代碼再一次進行封裝,已達到更優。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
衛星菜單可能網上已經有很多博文了,but,這裡僅記錄下自己的學習路程~剛看到自定義衛星菜單的時候真的是一臉懵逼,看完所有的源碼覺得還可以接受,自己寫難度較大,功力太薄嗚嗚
實現功能:實現網絡音樂搜索功能使用觀察者設計模式使用URLEncoder.encode轉碼SearchMusicUtils是重點實現效果如圖:實現代碼如下:NetMusi
先看效果圖:(以公司附近的國貿為中心點)上面是地圖,下面是地理位置列表,有的只有地理位置列表(QQ動態的位置),這是個很常見的功能。它有個專門的叫法:POI周邊搜索。實現
前言話說在android這座大山裡,有一座廟(方塊公司-square),廟裡住著一個神-jake(我是這麼叫的嘻嘻)。不要小看這個小jake,這個神可是為android應