Android開原始碼解讀の地圖照片應用Panoramio的實現詳解(四)

來源:互聯網
上載者:User

本文繼續講解Panoramio的實現,主要介紹ImageAdapter.java和ImageList.java 這兩個檔案,這兩個檔案實現了如下所示的介面,左圖是資料從網路載入過程中,有圖是載入完成後的效果:

                              

ImageAdapter繼承自BaseAdapter類,實現圖片適配器的功能,而ImageList則繼承自ListActivity,用於以列表形式顯示搜尋到的圖片資訊。介紹之前,先來普及下DataSetObserver和DataSetObservable的知識。

從名字可以依稀猜到,DataSetObserver實現了觀察者模式中的觀察者角色(Observer)。當資料集發生變化或者變為無效時,DataSetObserver中的方法被回調,典型的資料集有Cursor和Adapter,當某個對象要添加到DataSetObservable中時,這個對象必須從DataSetObserver繼承,DataSetObserver是一個抽象類別,定義如下:

public abstract class DataSetObserver {<br /> /**<br /> * This method is called when the entire data set has changed,<br /> * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.<br /> */<br /> public void onChanged() {<br /> // Do nothing<br /> }</p><p> /**<br /> * This method is called when the entire data becomes invalid,<br /> * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a<br /> * {@link Cursor}.<br /> */<br /> public void onInvalidated() {<br /> // Do nothing<br /> }<br />}

而DataSetObservable實現了觀察者模式中的對象角色(Subject),它是Observable的具體實現,提供了調用DataSetObserver中各種回呼函數的方法,定義如下所示:

public class DataSetObservable extends Observable<DataSetObserver> {<br /> /**<br /> * Invokes onChanged on each observer. Called when the data set being observed has<br /> * changed, and which when read contains the new state of the data.<br /> */<br /> public void notifyChanged() {<br /> synchronized(mObservers) {<br /> for (DataSetObserver observer : mObservers) {<br /> observer.onChanged();<br /> }<br /> }<br /> }</p><p> /**<br /> * Invokes onInvalidated on each observer. Called when the data set being monitored<br /> * has changed such that it is no longer valid.<br /> */<br /> public void notifyInvalidated() {<br /> synchronized (mObservers) {<br /> for (DataSetObserver observer : mObservers) {<br /> observer.onInvalidated();<br /> }<br /> }<br /> }<br />}

注意這裡的Observable是定義在android.database包中的,而不是JDK中的Observable,它的定義如下:

package android.database;</p><p>import java.util.ArrayList;</p><p>/**<br /> * Provides methods for (un)registering arbitrary observers in an ArrayList.<br /> */<br />public abstract class Observable<T> {<br /> /**<br /> * The list of observers. An observer can be in the list at most<br /> * once and will never be null.<br /> */<br /> protected final ArrayList<T> mObservers = new ArrayList<T>();</p><p> /**<br /> * Adds an observer to the list. The observer cannot be null and it must not already<br /> * be registered.<br /> * @param observer the observer to register<br /> * @throws IllegalArgumentException the observer is null<br /> * @throws IllegalStateException the observer is already registered<br /> */<br /> public void registerObserver(T observer) {<br /> if (observer == null) {<br /> throw new IllegalArgumentException("The observer is null.");<br /> }<br /> synchronized(mObservers) {<br /> if (mObservers.contains(observer)) {<br /> throw new IllegalStateException("Observer " + observer + " is already registered.");<br /> }<br /> mObservers.add(observer);<br /> }<br /> }</p><p> /**<br /> * Removes a previously registered observer. The observer must not be null and it<br /> * must already have been registered.<br /> * @param observer the observer to unregister<br /> * @throws IllegalArgumentException the observer is null<br /> * @throws IllegalStateException the observer is not yet registered<br /> */<br /> public void unregisterObserver(T observer) {<br /> if (observer == null) {<br /> throw new IllegalArgumentException("The observer is null.");<br /> }<br /> synchronized(mObservers) {<br /> int index = mObservers.indexOf(observer);<br /> if (index == -1) {<br /> throw new IllegalStateException("Observer " + observer + " was not registered.");<br /> }<br /> mObservers.remove(index);<br /> }<br /> }</p><p> /**<br /> * Remove all registered observer<br /> */<br /> public void unregisterAll() {<br /> synchronized(mObservers) {<br /> mObservers.clear();<br /> }<br /> }<br />}

對觀察者模式的詳細描述,可見這篇文章http://blog.csdn.net/ace1985/article/details/5753658 。OK,言歸正傳,還是來看下我們的ImageAdapter.java,從上面的分析和代碼裡面的注釋應該很好理解了:

package com.google.android.panoramio;</p><p>import android.content.Context;<br />import android.database.DataSetObserver;<br />import android.view.LayoutInflater;<br />import android.view.View;<br />import android.view.ViewGroup;<br />import android.widget.BaseAdapter;<br />import android.widget.ImageView;<br />import android.widget.TextView;</p><p>/**<br /> * 用來給ImageList綁定圖片資源的適配器<br /> */<br />public class ImageAdapter extends BaseAdapter {</p><p> /**<br /> * Maintains the state of our data<br /> */<br /> private ImageManager mImageManager;</p><p> private Context mContext;</p><p> private MyDataSetObserver mObserver;</p><p> /**<br /> * ImageManager扮演的是Subject的角色,這個類的執行個體將被添加到ImagManager類<br /> * 中的觀察者列表中,當ImageList中的資料發生變化時(由ImageManager來檢測)<br /> * ImageManager將通告MyDataSetObserver執行個體發生的變化<br /> */<br /> private class MyDataSetObserver extends DataSetObserver {<br /> @Override<br /> public void onChanged() {<br /> //BaseAdapter維護了一個DataSetObservable對象mDataSetObservable<br /> //這個函數用於通告mDataSetObservable的所有觀察者資料發生變化<br /> notifyDataSetChanged();<br /> }</p><p> @Override<br /> public void onInvalidated() {<br /> //BaseAdapter維護了一個DataSetObservable對象mDataSetObservable<br /> //這個函數用於通告mDataSetObservable的所有觀察者資料變為無效<br /> notifyDataSetInvalidated();<br /> }<br /> }</p><p> public ImageAdapter(Context c) {<br /> mImageManager = ImageManager.getInstance(c);<br /> mContext = c;<br /> mObserver = new MyDataSetObserver();</p><p> mImageManager.addObserver(mObserver); //將mObserver設定為mImageManager的觀察者<br /> }</p><p> /**<br /> * 返回顯示的圖片的數目<br /> *<br /> * @see android.widget.Adapter#getCount()<br /> */<br /> public int getCount() {<br /> return mImageManager.size();<br /> }</p><p> /**<br /> * 返回指定索引的圖片<br /> *<br /> * @see android.widget.Adapter#getItem(int)<br /> */<br /> public Object getItem(int position) {<br /> return mImageManager.get(position);<br /> }</p><p> /**<br /> * 返回指定索引的圖片ID<br /> *<br /> * @see android.widget.Adapter#getItemId(int)<br /> */<br /> public long getItemId(int position) {<br /> PanoramioItem s = mImageManager.get(position);<br /> return s.getId();<br /> }</p><p> /**<br /> * 返回指定索引處用於顯示圖片的view<br /> *<br /> * @param position 索引<br /> * @param convertView 可以重用的view,可能為null.<br /> * @param parent 返回的view的父view.<br /> * @return 用於顯示指定索引處圖片的view<br /> */<br /> public View getView(int position, View convertView, ViewGroup parent) {<br /> View view;<br /> if (convertView == null) {<br /> // 建立新的view<br /> LayoutInflater inflater = (LayoutInflater) mContext<br /> .getSystemService(Context.LAYOUT_INFLATER_SERVICE);<br /> view = inflater.inflate(R.layout.image_item, null);<br /> } else {<br /> // 使用已經存在的view<br /> view = convertView;<br /> }<br /> PanoramioItem s = mImageManager.get(position);</p><p> ImageView i = (ImageView) view.findViewById(R.id.image);<br /> i.setImageBitmap(s.getBitmap()); //將位元影像設定到view上<br /> i.setBackgroundResource(R.drawable.picture_frame); //設定ImageView的背景圖片</p><p> TextView t = (TextView) view.findViewById(R.id.title);<br /> t.setText(s.getTitle()); //設定圖片名稱</p><p> t = (TextView) view.findViewById(R.id.owner);<br /> t.setText(s.getOwner()); //設定圖片作者<br /> return view;<br /> }</p><p>}

同理,ImageList.java檔案內容如下所示:

package com.google.android.panoramio;</p><p>import android.app.ListActivity;<br />import android.content.Context;<br />import android.content.Intent;<br />import android.database.DataSetObserver;<br />import android.os.Bundle;<br />import android.view.LayoutInflater;<br />import android.view.View;<br />import android.view.Window;<br />import android.widget.ListView;</p><p>/**<br /> * 顯示圖片列表的Activity<br /> */<br />public class ImageList extends ListActivity {</p><p> ImageManager mImageManager;</p><p> private MyDataSetObserver mObserver = new MyDataSetObserver();</p><p> /**<br /> * 儲存使用者在主介面選取搜尋地區時所用的縮放層級<br /> */<br /> private int mZoom;</p><p> /**<br /> * 儲存使用者在主介面選取的搜尋地區的中心點緯度<br /> */<br /> private int mLatitudeE6;</p><p> /**<br /> * 儲存使用者在主介面選取的搜尋地區的中心點經度<br /> */<br /> private int mLongitudeE6;</p><p> /**<br /> * 註冊為ImageManager執行個體的觀察者,用於當ImageManager結束圖片下載時將ImageList介面上的載入進度顯示關閉<br /> */<br /> private class MyDataSetObserver extends DataSetObserver {<br /> @Override<br /> public void onChanged() {<br /> if (!mImageManager.isLoading()) {<br /> getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,<br /> Window.PROGRESS_VISIBILITY_OFF);<br /> }<br /> }</p><p> @Override<br /> public void onInvalidated() {<br /> }<br /> }</p><p> @Override<br /> public void onCreate(Bundle savedInstanceState) {<br /> requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);//顯示不確定進度<br /> super.onCreate(savedInstanceState);</p><p> mImageManager = ImageManager.getInstance(this);</p><p> //擷取ListView,並在底部添加著作權資訊<br /> ListView listView = getListView();<br /> LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);<br /> View footer = inflater.inflate(R.layout.list_footer, listView, false);<br /> listView.addFooterView(footer, null, false);</p><p> //將自訂的ImageAdapter設定給這個ListActivity<br /> setListAdapter(new ImageAdapter(this));</p><p> //在AndroidManifest.xml檔案中為我們的List設定了Theme.Light,這裡將背景移除<br /> listView.setBackgroundDrawable(null);<br /> //當ImageManager還在下載資源時,顯示進度條為忙,並註冊觀察者用於下載結束時隱藏進度條<br /> if (mImageManager.isLoading()) {<br /> getWindow().setFeatureInt(Window.FEATURE_INDETERMINATE_PROGRESS,<br /> Window.PROGRESS_VISIBILITY_ON);<br /> mImageManager.addObserver(mObserver);<br /> }</p><p> //儲存從Panoramio主介面傳過來的搜尋地區相關資訊<br /> Intent i = getIntent();<br /> mZoom = i.getIntExtra(ImageManager.ZOOM_EXTRA, Integer.MIN_VALUE);<br /> mLatitudeE6 = i.getIntExtra(ImageManager.LATITUDE_E6_EXTRA, Integer.MIN_VALUE);<br /> mLongitudeE6 = i.getIntExtra(ImageManager.LONGITUDE_E6_EXTRA, Integer.MIN_VALUE);<br /> }</p><p> @Override<br /> protected void onListItemClick(ListView l, View v, int position, long id) {<br /> PanoramioItem item = mImageManager.get(position); </p><p> //建立Intent用於傳遞相關資料給ViewImage,用於顯示單張圖片資訊<br /> Intent i = new Intent(this, ViewImage.class);<br /> i.putExtra(ImageManager.PANORAMIO_ITEM_EXTRA, item);<br /> i.putExtra(ImageManager.ZOOM_EXTRA, mZoom);<br /> i.putExtra(ImageManager.LATITUDE_E6_EXTRA, mLatitudeE6);<br /> i.putExtra(ImageManager.LONGITUDE_E6_EXTRA, mLongitudeE6);<br /> startActivity(i);<br /> } </p><p>}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.