Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> ANDROID多種布局的列表實現

ANDROID多種布局的列表實現

編輯:關於Android編程

 這個我也問了同事以及開發群裡的朋友,居然都沒得到最優的實現方式的回答,看來這種復雜列表的需求還是比較少的,我自己也走了一些彎路,把我幾個實現的方式整理下,希望對於還不了解的朋友有所幫助。       實現方式1:(每次getView時重新inflate itemView,convertView沒有復用,性能低,運行沒問題)     private class MyAdapter extends BaseAdapter{           private List<Object> datas = Collections.EMPTY_LIST;           public void setDatas(List<Object> datas) {             if(datas == null){                 datas = Collections.EMPTY_LIST;             }             this.datas = datas;             notifyDataSetChanged();         }           @Override         public int getCount() {             return datas.size();         }           @Override         public Object getItem(int position) {             return datas.get(position);         }           @Override         public long getItemId(int position) {             return 0;         }           @Override         public View getView(int position, View convertView, ViewGroup parent) {             Object data = getItem(position);               if(data instanceof Folder){                 FolderViewHolder holder = null;                 if(convertView != null && convertView.getTag() instanceof FolderViewHolder){                     //View與數據類型一致                     holder = (FolderViewHolder) convertView.getTag();                 }else{                     convertView = mInflater.inflate(R.layout.listitem1, null);                     holder = new FolderViewHolder(convertView);                     convertView.setTag(holder);                 }                 holder.setData((Folder)data);             }else{                 FileViewHolder holder = null;                 if(convertView != null && convertView.getTag() instanceof FileViewHolder){                     //View與數據類型一致                     holder = (FileViewHolder) convertView.getTag();                 }else{                     convertView = mInflater.inflate(R.layout.listitem2, null);                     holder = new FileViewHolder(convertView);                     convertView.setTag(holder);                 }                 holder.setData((File)data);             }               return convertView;         }     }       private class FolderViewHolder{         public TextView tvName;           public FolderViewHolder(View itemView){             tvName = (TextView) itemView.findViewById(R.id.tvName);         }           public void setData(Folder data) {             tvName.setText(data.name);         }     }       private class FileViewHolder{         public TextView tvName;           public FileViewHolder(View itemView){             tvName = (TextView) itemView.findViewById(R.id.tvName);         }           public void setData(File data) {             tvName.setText(data.name);         }     }       實現方式2:(因為方式1不斷inflate view,影響性能,於是考慮是否能盡可能重用已經inflate的view,於是添加了一個緩存,不過實際測試快速滑動或切換數據會顯示異常,應該是AbsListView#RecycleBin緩存的原因,具體原因我後面理清了再添加,看別人的代碼最痛苦了。。。)     private class MyAdapter extends BaseAdapter{           private List<View> folderViewCaches = new ArrayList<View>(5);         private List<View> fileViewCaches = new ArrayList<View>(5);           private List<Object> datas = Collections.EMPTY_LIST;           public void setDatas(List<Object> datas) {             if(datas == null){                 datas = Collections.EMPTY_LIST;             }             this.datas = datas;             notifyDataSetChanged();         }           @Override         public int getCount() {             return datas.size();         }           @Override         public Object getItem(int position) {             return datas.get(position);         }           @Override         public long getItemId(int position) {             return 0;         }           @Override         public View getView(int position, View convertView, ViewGroup parent) {             Object data = getItem(position);               if(data instanceof Folder){                 //文件夾,應該返回R.layout.listitem1對應的View                 FolderViewHolder holder = null;                 if(convertView != null && convertView.getTag() instanceof FolderViewHolder){                     //View與數據類型一致                     holder = (FolderViewHolder) convertView.getTag();                 }else{                     if(convertView != null){                         //緩存到文件列表                         fileViewCaches.add(convertView);                         convertView = null;                     }                       //從緩存裡面取已從ListView移除的緩存(注釋掉此部分代碼顯示正常)                     if(!folderViewCaches.isEmpty()){                         for(View cache : folderViewCaches){                             if(cache.getParent() == null){                                 //緩存的View已從listView裡面移除                                 convertView = cache;                                 holder = (FolderViewHolder) convertView.getTag();                                 folderViewCaches.remove(cache);                                 break;                             }                         }                     }                       //還是沒有,重新inflate                     if(convertView == null){                         convertView = mInflater.inflate(R.layout.listitem1, null);                         holder = new FolderViewHolder(convertView);                         convertView.setTag(holder);                     }                 }                   holder.setData((Folder) data);               }else{                 //文件,應該返回R.layout.listitem2對應的View                 FileViewHolder holder = null;                 if(convertView != null && convertView.getTag() instanceof FileViewHolder){                     //View與數據類型一致                     holder = (FileViewHolder) convertView.getTag();                 }else{                     if(convertView != null){                         //緩存到文件夾列表                         folderViewCaches.add(convertView);                         convertView = null;                     }                       //從緩存裡面取已從ListView移除的緩存(注釋掉此部分代碼顯示正常)                     if(!fileViewCaches.isEmpty()){                         for(View cache : fileViewCaches){                             if(cache.getParent() == null){                                 //緩存的View已從listView裡面移除                                 convertView = cache;                                 holder = (FileViewHolder) convertView.getTag();                                 fileViewCaches.remove(cache);                                 break;                             }                         }                     }                       //還是沒有,重新inflate                     if(convertView == null){                         convertView = mInflater.inflate(R.layout.listitem2, null);                         holder = new FileViewHolder(convertView);                         convertView.setTag(holder);                     }                 }                   holder.setData((File) data);             }               return convertView;         }     }     實現方式3:(最佳實現,運行正常)   後面仔細閱讀ListView相關源碼,才發現Adapter本身就支持不同的布局了,而且AbsListView#RecycleBin也支持不同類型的布局的緩存策略,RecycleBin.mViewTypeCount標示有多少種View類型。   我們需要做的就是重寫Adapter的下面3個方法:   1.getViewTypeCount:          /**          * 有多少種不同布局的View          */         @Override         public int getViewTypeCount() {             return 2;         }       2.getItemViewType             /**          * 相應position對應的View類型          */         @Override         public int getItemViewType(int position) {             if(getItem(position) instanceof Folder){                 return TYPE_FOLDER;             }else{                 return TYPE_FILE;             }         }           3.getView,通過判斷對應position的類型,返回相應類型的view:          @Override         public View getView(int position, View convertView, ViewGroup parent) {             Object data = getItem(position);               if(data instanceof Folder){                 //TYPE_FOLDER,文件夾,應該返回R.layout.listitem1對應的View                 FolderViewHolder holder = null;                 if(convertView != null){                     holder = (FolderViewHolder) convertView.getTag();                 }else{                     convertView = mInflater.inflate(R.layout.listitem1, null);                     holder = new FolderViewHolder(convertView);                     convertView.setTag(holder);                 }                   holder.setData((Folder) data);               }else{                 //TYPE_FILE,文件,應該返回R.layout.listitem2對應的View                 FileViewHolder holder = null;                 if(convertView != null){                     holder = (FileViewHolder) convertView.getTag();                 }else{                     convertView = mInflater.inflate(R.layout.listitem2, null);                     holder = new FileViewHolder(convertView);                     convertView.setTag(holder);                 }                   holder.setData((File) data);             }               return convertView;         }  
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved