Jamendo中大量使用了Adaper,Adaper的继承关系如下图所示:

 

为了解其设计的过程,将分别沿几条线路分析。

(一) HomeActivityTitleBar(ImageAdapter)的加载过程,涉及相关Adapter如下图所示:

 

从服务端获取数据之后,将数据给Gallery,代码如下:

 
  
  1. public void onPostExecute(Album[] albums) { 
  2.  
  3.             if(albums != null && albums.length > 0){ 
  4.                 mViewFlipper.setDisplayedChild(1); 
  5.                 ImageAdapter albumsAdapter = new ImageAdapter(HomeActivity.this); 
  6.                 albumsAdapter.setList(albums); 
  7.                 mGallery.setAdapter(albumsAdapter); 
  8.                 mGallery.setOnItemClickListener(mGalleryListener); 
  9.                 mGallery.setSelection(albums.length/2true); // animate to center 
  10.  
  11.             } else { 
  12.                 mViewFlipper.setDisplayedChild(2); 
  13.                 mFailureBar.setOnRetryListener(new OnClickListener(){ 
  14.  
  15.                     @Override 
  16.                     public void onClick(View v) { 
  17.                         new NewsTask().execute((Void)null); 
  18.                     } 
  19.  
  20.                 }); 
  21.                 mFailureBar.setText(R.string.connection_fail); 
  22.             } 
  23.             super.onPostExecute(albums); 
  24.         } 

1, 单击setList(),进入ArrayListAdapter中,代码如下:

 
  
  1. public void setList(T[] list){ 
  2.         ArrayList<T> arrayList = new ArrayList<T>(list.length);   
  3.         for (T t : list) {   
  4.             arrayList.add(t);   
  5.         }   
  6.         setList(arrayList); 
  7.     } 

A,使用了泛型,扩大了此类的使用范围,其继承类复用很多代码。

B, setList()方法重载,先将解析封装好的T[]传进来,再将T[]中每一个元素存入ArrayList中。代码如下:

 
  
  1. public void setList(ArrayList<T> list){ 
  2.         this.mList = list; 
  3.         notifyDataSetChanged();//刷新ui 
  4.     } 

C, 定义了抽象方法getView()。继承类中只需要实现其即可。经常写adapter就回知道,继承BaseAdapter需要implements四个方法,其中最主要的code内容在getView()方法中完成。在ArrayListAdapter中写一个抽象方法,继承类只需要实现getView方法,并完成其内部的代码即可。如上面的adpter tree diagram所示,ArrayListAdapter有六个子类,简化了代码。

 
  
  1. @Override 
  2.     abstract public View getView(int position, View convertView, ViewGroup parent);//抽象方法 

D,设置数据之后,即notifyDataSetChanged()刷新。显然是在重新封装成arrayList之后。

 
  
  1. public void setList(ArrayList<T> list){ 
  2.         this.mList = list; 
  3.         notifyDataSetChanged();//刷新ui 
  4.     } 

E, 此setListView()方法,暂时还没发现有什么用。如果以后遇到,再补充。

2, ImageAdapteritem其实很简单。就一个图片。继承AlbumAdapter,直接重载getView()方法。在内部写实现代码。仅在于简化代码。两者关系并不密切。AlbumAdapter仅比ImageAdapter复杂一点,ImageAdapter中getView()代码如下:

 
  
  1. @Override 
  2.     public View getView(int position, View convertView, ViewGroup parent) { 
  3.         RemoteImageView i; 
  4.  
  5.         if (convertView == null) { 
  6.             i = new RemoteImageView(mContext); 
  7.             i.setScaleType(RemoteImageView.ScaleType.FIT_CENTER); 
  8.             i.setLayoutParams(new Gallery.LayoutParams(mIconSize, mIconSize)); 
  9.         } else { 
  10.             i = (RemoteImageView) convertView; 
  11.         } 
  12.  
  13.         i.setDefaultImage(R.drawable.no_cd); 
  14.         i.setImageUrl(mList.get(position).getImage()); 
  15.  
  16.         return i; 
  17.     } 

3, 显然2中,Jamendo自定义了一个RemoteImageView,用来实现图片的下载和显示。

setImageUrl()的代码如下:

 
  
  1. public void setImageUrl(String url){ 
  2.          
  3. //      Log.d("img_url", "img_url is :" + url); 
  4.          
  5.         if (mUrl != null && mUrl.equals(url) && (mCurrentlyGrabbedUrl == null ||//1:url赋给全局变量mUrl,两者相等且都为空,但是未执行,所以mCurrentlyGrabbedUrl为空 
  6.                 (mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl.equals(url)))) {//2:第n(n>1)次执行时,并未完成downloadTask 
  7.             mFailure++;          
  8.             if(mFailure > MAX_FAILURES){//超过指定重连次数 
  9.                 Log.e(JamendoApplication.TAG, "Failed to download "+url+", falling back to default p_w_picpath"); 
  10.                 loadDefaultImage(); 
  11.                 return
  12.             } 
  13.         } else { 
  14.             mUrl = url; 
  15.             mFailure = 0
  16.         } 
  17.  
  18.         updateCacheSize(); 
  19.          
  20.         if (mCacheSize>0 && (url.contains(ALBUMS) || url.contains(RADIOS))) {//只有两类路径图片需要缓存          
  21.             String fileName = convertUrlToFileName(url); 
  22.             String dir = getDirectory(fileName); 
  23.             Log.d("img_url""dir is :" + dir); 
  24.             String pathFileName = dir + "/" + fileName; 
  25.             Log.d("img_url""pathFileName is :" + pathFileName); 
  26.             Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);//从指定文件保存路径解码处图片 
  27.             if (tbmp == null) { 
  28.                 Log.d(JamendoApplication.TAG, "Image is not present, try to download"); 
  29.                 try
  30.                     new DownloadTask().execute(url); 
  31.                 } catch (RejectedExecutionException e) { 
  32.                     // do nothing, just don't crash 
  33.                 } 
  34.             } else { 
  35.                 Log.i(JamendoApplication.TAG, "Loading album cover from file"); 
  36.                 this.setImageBitmap(tbmp); 
  37.                 updateFileTime(dir,fileName );               
  38.             } 
  39.              
  40.             removeAlbumCoversCache(dir, fileName);//对专辑图片的缓存处理:比较大120k 
  41.             removeRadioCoversCache(dir, fileName);//对广播图片的缓存处理:比较小8k 
  42.              
  43.         } 
  44.         else { 
  45.             Log.i(JamendoApplication.TAG, "File not cached supported" + url); 
  46.             ImageCache p_w_picpathCache = JamendoApplication.getInstance() 
  47.                     .getImageCache(); 
  48.             if (p_w_picpathCache.isCached(url)) {              
  49.                 this.setImageBitmap(p_w_picpathCache.get(url)); 
  50.             } else { 
  51.                 try { 
  52.                     Log.i(JamendoApplication.TAG, "Image is not present, try to download"); 
  53.                     new DownloadTask().execute(url); 
  54.                 } catch (RejectedExecutionException e) { 
  55.                     // do nothing, just don't crash 
  56.                 } 
  57.             } 
  58.         } 
  59.     } 

依照顺序,分析如下:

1st. 重连的判断

指定重连次数,不断请求,大于重连次数,设置为默认图片

2nd. 更新设置中的缓存大小

updateCacheSize();

3rd. 设置图片(先从缓存中找,没有再找SDCard,最后再下载)

缓存的问题将单独写一篇文章

至此:TitleBar的相关Adapter解析完毕。给人印象最深的仍然是面向对象的思想。A: 继承BaseAdapter所实现的4个方法中,3个都基本一样,所以构建父类 ArrayListAdapter。子类.

B: 封装RemoteImageView,可移植性增强。

Adapter的分析先到这里,后面如果发现比较特殊的adpter,会继续补充。