频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
Android开源代码解读の地图照片应用Panoramio的实现详解(四)
2012-02-24 10:30:56           
收藏   我要投稿

本文继续讲解Panoramio的实现,主要介绍ImageAdapter.java和ImageList.java 这两个文件,这两个文件实现了如下所示的界面,左图是数据从网络加载过程中,有图是加载完成后的效果:

 \\


 

ImageAdapter继承自BaseAdapter类,实现图片适配器的功能,而ImageList则继承自ListActivity,用于以列表形式显示搜索到的图片信息。介绍之前,先来普及下DataSetObserver和DataSetObservable的知识。

从名字可以依稀猜到,DataSetObserver实现了观察者模式中的观察者角色(Observer)。当数据集发生变化或者变为无效时,DataSetObserver中的方法被回调,典型的数据集有Cursor和Adapter,当某个对象要添加到DataSetObservable中时,这个对象必须从DataSetObserver继承,DataSetObserver是一个抽象类,定义如下:

[java]
public abstract class DataSetObserver {  

     /**
      * This method is called when the entire data set has changed,
      * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
      */
     public void onChanged() {
         // Do nothing 
     }
 
     /**
      * This method is called when the entire data becomes invalid,
      * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
      * {@link Cursor}.
      */
     public void onInvalidated() {
         // Do nothing 
     }
 }
 public abstract class DataSetObserver {
     /**
      * This method is called when the entire data set has changed,
      * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
      */
     public void onChanged() {
         // Do nothing
     }
 
    /**
      * This method is called when the entire data becomes invalid,
      * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
      * {@link Cursor}.
      */
     public void onInvalidated() {
         // Do nothing
     }
 }
 而DataSetObservable实现了观察者模式中的对象角色(Subject),它是Observable的具体实现,提供了调用DataSetObserver中各种回调函数的方法,定义如下所示:
 
[java]
 public class DataSetObservable extends Observable<DataSetObserver> {
     /**
      * Invokes onChanged on each observer. Called when the data set being observed has
      * changed, and which when read contains the new state of the data.
      */
     public void notifyChanged() {
         synchronized(mObservers) {
             for (DataSetObserver observer : mObservers) {
                 observer.onChanged();
             }
         }
     }
 
     /**
      * Invokes onInvalidated on each observer. Called when the data set being monitored
      * has changed such that it is no longer valid.
      */
     public void notifyInvalidated() {
         synchronized (mObservers) {
             for (DataSetObserver observer : mObservers) {
                 observer.onInvalidated();
             }
         }
     }
 }
 public class DataSetObservable extends Observable<DataSetObserver> {
     /**
      * Invokes onChanged on each observer. Called when the data set being observed has
      * changed, and which when read contains the new state of the data.
      */
     public void notifyChanged() {
         synchronized(mObservers) {
             for (DataSetObserver observer : mObservers) {
                 observer.onChanged();
             }
         }
     }
 
    /**
      * Invokes onInvalidated on each observer. Called when the data set being monitored
      * has changed such that it is no longer valid.
      */
     public void notifyInvalidated() {
         synchronized (mObservers) {
             for (DataSetObserver observer : mObservers) {
                 observer.onInvalidated();
             }
         }
     }
 }
 注意这里的Observable是定义在android.database包中的,而不是JDK中的Observable,它的定义如下:
 
[java]
 package android.database;
 
 import java.util.ArrayList;
 
 /**
  * Provides methods for (un)registering arbitrary observers in an ArrayList.
  */
 public abstract class Observable<T> {
     /**
      * The list of observers.  An observer can be in the list at most
      * once and will never be null.
      */
     protected final ArrayList<T> mObservers = new ArrayList<T>();
 
     /**
      * Adds an observer to the list. The observer cannot be null and it must not already
      * be registered.
      * @param observer the observer to register
      * @throws IllegalArgumentException the observer is null
      * @throws IllegalStateException the observer is already registered
      */
     public void registerObserver(T observer) {
         if (observer == null) {
             throw new IllegalArgumentException("The observer is null.");
         }
         synchronized(mObservers) {
             if (mObservers.contains(observer)) {
                 throw new IllegalStateException("Observer " + observer + " is already registered.");
             }
             mObservers.add(observer);
         }
     }
 
     /**
      * Removes a previously registered observer. The observer must not be null and it
      * must already have been registered.
      * @param observer the observer to unregister
      * @throws IllegalArgumentException the observer is null
      * @throws IllegalStateException the observer is not yet registered
      */
     public void unregisterObserver(T observer) {
         if (observer == null) {
             throw new IllegalArgumentException("The observer is null.");
         }
         synchronized(mObservers) {
             int index = mObservers.indexOf(observer);
             if (index == -1) {
                 throw new IllegalStateException("Observer " + observer + " was not registered.");
             }
             mObservers.remove(index);
         }
     }
     
     /**
      * Remove all registered observer
      */
     public void unregisterAll() {
         synchronized(mObservers) {
             mObservers.clear();
         }        
     }
 }
 package android.database;
 
import java.util.ArrayList;
 
/**
  * Provides methods for (un)registering arbitrary observers in an ArrayList.
  */
 public abstract class Observable<T> {
     /**
      * The list of observers.  An observer can be in the list at most
      * once and will never be null.
      */
     protected final ArrayList<T> mObservers = new ArrayList<T>();
 
    /**
      * Adds an observer to the list. The observer cannot be null and it must not already
      * be registered.
      * @param observer the observer to register
      * @throws IllegalArgumentException the observer is null
      * @throws IllegalStateException the observer is already registered
      */
     public void registerObserver(T observer) {
         if (observer == null) {
             throw new IllegalArgumentException("The observer is null.");
         }
         synchronized(mObservers) {
             if (mObservers.contains(observer)) {
                 throw new IllegalStateException("Observer " + observer + " is already registered.");
             }
             mObservers.add(observer);
         }
     }
 
    /**
      * Removes a previously registered observer. The observer must not be null and it
      * must already have been registered.
      * @param observer the observer to unregister
      * @throws IllegalArgumentException the observer is null
      * @throws IllegalStateException the observer is not yet registered
      */
     public void unregisterObserver(T observer) {
         if (observer == null) {
             throw new IllegalArgumentException("The observer is null.");
         }
         synchronized(mObservers) {
             int index = mObservers.indexOf(observer);
             if (index == -1) {
                 throw new IllegalStateException("Observer " + observer + " was not registered.");
             }
             mObservers.remove(index);
         }
     }
   
     /**
      * Remove all registered observer
      */
     public void unregisterAll() {
         synchronized(mObservers) {
             mObservers.clear();
         }      
     }
 }
 对观察者模式的详细描述,可见这篇文章/index.php?m=content&c=content&a=public_preview&steps=1&catid=339&id=120756 。OK,言归正传,还是来看下我们的ImageAdapter.java,从上面的分析和代码里面的注释应该很好理解了:
 
[java]
 package com.google.android.panoramio;
 
 import android.content.Context;
 import android.database.DataSetObserver;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 /**
  * 用来给ImageList绑定图片资源的适配器
  */
 public class ImageAdapter extends BaseAdapter {
 
     /**
      * Maintains the state of our data
      */
     private ImageManager mImageManager;
 
     private Context mContext;
     
     private MyDataSetObserver mObserver;
 
     /**
      * ImageManager扮演的是Subject的角色,这个类的实例将被添加到ImagManager类
      * 中的观察者列表中,当ImageList中的数据发生变化时(由ImageManager来检测)
      * ImageManager将通告MyDataSetObserver实例发生的变化
      */
     private class MyDataSetObserver extends DataSetObserver {
         @Override
         public void onChanged() {
             //BaseAdapter维护了一个DataSetObservable对象mDataSetObservable 
             //这个函数用于通告mDataSetObservable的所有观察者数据发生变化 
             notifyDataSetChanged(); 
         }
 
         @Override
         public void onInvalidated() {
             //BaseAdapter维护了一个DataSetObservable对象mDataSetObservable 
             //这个函数用于通告mDataSetObservable的所有观察者数据变为无效 
             notifyDataSetInvalidated();
         }
     }
     
     public ImageAdapter(Context c) {
         mImageManager = ImageManager.getInstance(c);
         mContext = c;
         mObserver = new MyDataSetObserver();
         
         mImageManager.addObserver(mObserver); //将mObserver设置为mImageManager的观察者 
     }
 
     /**
      * 返回显示的图片的数目
      *
      * @see android.widget.Adapter#getCount()
      */
     public int getCount() {
         return mImageManager.size();
     }
 
     /**
      * 返回指定索引的图片
      *
      * @see android.widget.Adapter#getItem(int)
      */
     public Object getItem(int position) {
         return mImageManager.get(position);
     }
 
     /**
      * 返回指定索引的图片ID
      *
      * @see android.widget.Adapter#getItemId(int)
      */
     public long getItemId(int position) {
         PanoramioItem s = mImageManager.get(position);
         return s.getId();
     }
 
     /**
      * 返回指定索引处用于显示图片的view
      *
      * @param position 索引
      * @param convertView 可以重用的view,可能为null.
      * @param parent 返回的view的父view.
      * @return 用于显示指定索引处图片的view
      */
     public View getView(int position, View convertView, ViewGroup parent) {
         View view;
         if (convertView == null) {
             // 创建新的view 
             LayoutInflater inflater = (LayoutInflater) mContext
                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             view = inflater.inflate(R.layout.image_item, null);
         } else {
             // 使用已经存在的view 
             view = convertView;
         }
         PanoramioItem s = mImageManager.get(position);
 
         ImageView i = (ImageView) view.findViewById(R.id.image);
         i.setImageBitmap(s.getBitmap()); //将位图设置到view上 
         i.setBackgroundResource(R.drawable.picture_frame); //设置ImageView的背景图片 
         
         TextView t = (TextView) view.findViewById(R.id.title);
         t.setText(s.getTitle()); //设置图片名称 
         
         t = (TextView) view.findViewById(R.id.owner);
         t.setText(s.getOwner()); //设置图片作者 
         return view;
     }
 
 }
 package com.google.android.panoramio;
 
import android.content.Context;
 import android.database.DataSetObserver;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
 import android.widget.TextView;
 
/**
  * 用来给ImageList绑定图片资源的适配器
  */
 public class ImageAdapter extends BaseAdapter {
 
    /**
      * Maintains the state of our data
      */
     private ImageManager mImageManager;
 
    private Context mContext;
   
     private MyDataSetObserver mObserver;
 
    /**
      * ImageManager扮演的是Subject的角色,这个类的实例将被添加到ImagManager类
      * 中的观察者列表中,当ImageList中的数据发生变化时(由ImageManager来检测)
      * ImageManager将通告MyDataSetObserver实例发生的变化
      */
     private class MyDataSetObserver extends DataSetObserver {
         @Override
         public void onChanged() {
          //BaseAdapter维护了一个DataSetObservable对象mDataSetObservable
          //这个函数用于通告mDataSetObservable的所有观察者数据发生变化
             notifyDataSetChanged();
         }
 
        @Override
         public void onInvalidated() {
          //BaseAdapter维护了一个DataSetObservable对象mDataSetObservable
          //这个函数用于通告mDataSetObservable的所有观察者数据变为无效
             notifyDataSetInvalidated();
         }
     }
   
     public ImageAdapter(Context c) {
         mImageManager = ImageManager.getInstance(c);
         mContext = c;
         mObserver = new MyDataSetObserver();
       
         mImageManager.addObserver(mObserver); //将mObserver设置为mImageManager的观察者
     }
 
    /**
      * 返回显示的图片的数目
      *
      * @see android.widget.Adapter#getCount()
      */
     public int getCount() {
         return mImageManager.size();
     }
 
    /**
      * 返回指定索引的图片
      *
      * @see android.widget.Adapter#getItem(int)
      */
     public Object getItem(int position) {
         return mImageManager.get(position);
     }
 
    /**
      * 返回指定索引的图片ID
      *
      * @see android.widget.Adapter#getItemId(int)
      */
     public long getItemId(int position) {
         PanoramioItem s = mImageManager.get(position);
         return s.getId();
     }
 
    /**
      * 返回指定索引处用于显示图片的view
      *
      * @param position 索引
      * @param convertView 可以重用的view,可能为null.
      * @param parent 返回的view的父view.
      * @return 用于显示指定索引处图片的view
      */
     public View getView(int position, View convertView, ViewGroup parent) {
         View view;
         if (convertView == null) {
             // 创建新的view
             LayoutInflater inflater = (LayoutInflater) mContext
                     .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             view = inflater.inflate(R.layout.image_item, null);
         } else {
             // 使用已经存在的view
             view = convertView;
         }
         PanoramioItem s = mImageManager.get(position);
 
        ImageView i = (ImageView) view.findViewById(R.id.image);
         i.setImageBitmap(s.getBitmap()); //将位图设置到view上
         i.setBackgroundResource(R.drawable.picture_frame); //设置ImageView的背景图片
       
         TextView t = (TextView) view.findViewById(R.id.title);
         t.setText(s.getTitle()); //设置图片名称
       
         t = (TextView) view.findViewById(R.id.owner);
         t.setText(s.getOwner()); //设置图片作者
         return view;
     }
 
}
 同理,ImageList.java文件内容如下所示:
 
[java]
 package com.google.android.panoramio;
 
 import android.app.ListActivity;
 import android.content.Context;
 import android.content.Intent;
 import android.database.DataSetObserver;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.Window;
 import android.widget.ListView;
 
 /**
  * 显示图片列表的Activity
  */
 public class ImageList extends ListActivity {
     
     ImageManager mImageManager;
     
     private MyDataSetObserver mObserver = new MyDataSetObserver();
 
     /**
      * 保存用户在主界面选取搜索区域时所用的缩放级别
      */
     private int mZoom;
 
     /**
      * 保存用户在主界面选取的搜索区域的中心点纬度
      */
     private int mLatitudeE6;
 
     /**
      * 保存用户在主界面选取的搜索区域的中心点经度
      */
     private int mLongitudeE6;
 
     /**
      * 注册为ImageManager实例的观察者,用于当ImageManager结束图片下载时将ImageList界面上的加载进度显示关闭
      */
     private class MyDataSetObserver extends DataSetObserver {
         @Override
         public void onChanged() {
             if (!mImageManager.isLoading()) {
                 getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
                         Window.PROGRESS_VISIBILITY_OFF);
             }
         }
 
         @Override
         public void onInvalidated() {
         }
     }
     
     @Override
     public void onCreate(Bundle savedInstanceState) {
         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);//显示不确定进度 
         super.onCreate(savedInstanceState);
         
         mImageManager = ImageManager.getInstance(this);
         
         //获取ListView,并在底部添加版权信息 
         ListView listView = getListView();
         LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         View footer = inflater.inflate(R.layout.list_footer, listView, false);
         listView.addFooterView(footer, null, false);
         
         //将自定义的ImageAdapter设置给这个ListActivity 
         setListAdapter(new ImageAdapter(this));
 
         //在AndroidManifest.xml文件中为我们的List设置了Theme.Light,这里将背景移除 
         listView.setBackgroundDrawable(null);
         //当ImageManager还在下载资源时,显示进度条为忙,并注册观察者用于下载结束时隐藏进度条 
         if (mImageManager.isLoading()) {
             getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,
                     Window.PROGRESS_VISIBILITY_ON);
             mImageManager.addObserver(mObserver);
         }
         
         //保存从Panoramio主界面传过来的搜索区域相关信息 
         Intent i = getIntent();
         mZoom = i.getIntExtra(ImageManager.ZOOM_EXTRA, Integer.MIN_VALUE);
         mLatitudeE6 = i.getIntExtra(ImageManager.LATITUDE_E6_EXTRA, Integer.MIN_VALUE);
         mLongitudeE6 = i.getIntExtra(ImageManager.LONGITUDE_E6_EXTRA, Integer.MIN_VALUE);
     }
 
     @Override
     protected void onListItemClick(ListView l, View v, int position, long id) {
         PanoramioItem item = mImageManager.get(position);   
         
         //创建Intent用于传递相关数据给ViewImage,用于显示单张图片信息 
         Intent i = new Intent(this, ViewImage.class);
         i.putExtra(ImageManager.PANORAMIO_ITEM_EXTRA, item);
         i.putExtra(ImageManager.ZOOM_EXTRA, mZoom);
         i.putExtra(ImageManager.LATITUDE_E6_EXTRA, mLatitudeE6);
         i.putExtra(ImageManager.LONGITUDE_E6_EXTRA, mLongitudeE6);
         startActivity(i);
     }   
     
 }
 
 摘自ASCE1885
点击复制链接 与好友分享!回本站首页
相关TAG标签 代码 地图 照片
上一篇:Android开源代码解读の地图照片应用Panoramio的实现详解(三)
下一篇:android 用webview自制带有history和download功能的浏览器
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站