您的位置:首页 > 其它

Jamendo学习笔记之五:Adpter框架

2012-05-22 13:49 316 查看
Jamendo中大量使用了Adaper,Adaper的继承关系如下图所示:





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

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





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

public void onPostExecute(Album[] albums) {

if(albums != null && albums.length > 0){
mViewFlipper.setDisplayedChild(1);
ImageAdapter albumsAdapter = new ImageAdapter(HomeActivity.this);
albumsAdapter.setList(albums);
mGallery.setAdapter(albumsAdapter);
mGallery.setOnItemClickListener(mGalleryListener);
mGallery.setSelection(albums.length/2, true); // animate to center

} else {
mViewFlipper.setDisplayedChild(2);
mFailureBar.setOnRetryListener(new OnClickListener(){

@Override
public void onClick(View v) {
new NewsTask().execute((Void)null);
}

});
mFailureBar.setText(R.string.connection_fail);
}
super.onPostExecute(albums);
}

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

public void setList(T[] list){
ArrayList<T> arrayList = new ArrayList<T>(list.length);
for (T t : list) {
arrayList.add(t);
}
setList(arrayList);
}

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

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

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

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

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

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

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

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

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
RemoteImageView i;

if (convertView == null) {
i = new RemoteImageView(mContext);
i.setScaleType(RemoteImageView.ScaleType.FIT_CENTER);
i.setLayoutParams(new Gallery.LayoutParams(mIconSize, mIconSize));
} else {
i = (RemoteImageView) convertView;
}

i.setDefaultImage(R.drawable.no_cd);
i.setImageUrl(mList.get(position).getImage());

return i;
}

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

setImageUrl()的代码如下:

public void setImageUrl(String url){

//      Log.d("img_url", "img_url is :" + url);

if (mUrl != null && mUrl.equals(url) && (mCurrentlyGrabbedUrl == null ||//1:url赋给全局变量mUrl,两者相等且都为空,但是未执行,所以mCurrentlyGrabbedUrl为空
(mCurrentlyGrabbedUrl != null && !mCurrentlyGrabbedUrl.equals(url)))) {//2:第n(n>1)次执行时,并未完成downloadTask
mFailure++;
if(mFailure > MAX_FAILURES){//超过指定重连次数
Log.e(JamendoApplication.TAG, "Failed to download "+url+", falling back to default image");
loadDefaultImage();
return;
}
} else {
mUrl = url;
mFailure = 0;
}

updateCacheSize();

if (mCacheSize>0 && (url.contains(ALBUMS) || url.contains(RADIOS))) {//只有两类路径图片需要缓存
String fileName = convertUrlToFileName(url);
String dir = getDirectory(fileName);
Log.d("img_url", "dir is :" + dir);
String pathFileName = dir + "/" + fileName;
Log.d("img_url", "pathFileName is :" + pathFileName);
Bitmap tbmp = BitmapFactory.decodeFile(pathFileName);//从指定文件保存路径解码处图片
if (tbmp == null) {
Log.d(JamendoApplication.TAG, "Image is not present, try to download");
try{
new DownloadTask().execute(url);
} catch (RejectedExecutionException e) {
// do nothing, just don't crash
}
} else {
Log.i(JamendoApplication.TAG, "Loading album cover from file");
this.setImageBitmap(tbmp);
updateFileTime(dir,fileName );
}

removeAlbumCoversCache(dir, fileName);//对专辑图片的缓存处理:比较大120k
removeRadioCoversCache(dir, fileName);//对广播图片的缓存处理:比较小8k

}
else {
Log.i(JamendoApplication.TAG, "File not cached supported" + url);
ImageCache imageCache = JamendoApplication.getInstance()
.getImageCache();
if (imageCache.isCached(url)) {
this.setImageBitmap(imageCache.get(url));
} else {
try {
Log.i(JamendoApplication.TAG, "Image is not present, try to download");
new DownloadTask().execute(url);
} catch (RejectedExecutionException e) {
// do nothing, just don't crash
}
}
}
}

依照顺序,分析如下:

1st. 重连的判断

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

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

updateCacheSize();

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

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

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

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

Adapter的分析先到这里,后面如果发现比较特殊的adpter,会继续补充。
本文出自 “小新专栏” 博客,请务必保留此出处http://mikewang.blog.51cto.com/3826268/872453
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: