星期二, 11月 15, 2011

Fragment (十)

Adnrdoid應用程式學習筆記

Coordinating with the activity lifecycle

Fragment的寄主activity的生命週期直接影響fragment的生命週期,如此,activity的生命週期回呼方法與fragment的生命週期回呼方法類似,例如,當activity接收onPause()方法,在activity中的每個fragment也接收onPause()方法。

Fragment也有一些額外的回呼方法,然而,這些方法用來處理與activity的互動,完成一些動作比如建立或移除fragment的UI,這些額外的回呼方法有:

onAttach()
當fragment與activity聯合的時候呼叫此方法。
onCreateView()
呼叫此方法建立與fragment聯合的視圖階層。 
onActivityCreated()
當activity的onCreate()方法執行完呼叫此方法。
onDestoryView()
當與fragment有關的視圖階層移除時呼叫此方法。
onDetach()
當fragment不'要與activtiy聯合時呼叫此方法。 
fragment的生命週期流程,以及如何受寄主activity影響,都顯示在圖中。


在此圖中,你可以觀察activity的接替的狀態如何決定fragement接收哪一個回呼方法。舉例,當activity已經接收onCreate()方法的回呼,在activity的fragment只有接收onActivityCreated()方法回呼。

一旦activity處於resumed狀態,你可以自由地對activity增加或是移除fragment,因此,只有在activity是resumed狀態,fragment的生命週期才能獨立地改變。

然而,當activity離開resumed狀態,fragment再次由activity推動fragment的生命週期。
 

星期一, 11月 14, 2011

Fragment (九)

Android應用程式學習筆記

Handling the Fragment Lifecycle

管理fragment的生命週期非常像在管理activity的生命週期,如activity,fragment也存在三個狀態:

Resumed:
Fragment在運行中的activity是可見的。
Paused:
其他的activity在前台且擁有焦點,但是在activity的該fragment仍是可見的(前台activity部分是透明的或沒有完全覆蓋屏幕)。
Stopped:
Fragment已不可見,一方面可能是寄主activity已經停止或是fragment已經從activity被移除,但被加到back stack中。被停止的fragment仍是活的(所有的狀態和變數資訊都由系統保存),然而,fragment不再被用戶所見且如果activity被殺掉fragment也會被殺掉。
也像activity一樣,可以利用Bundle保留fragment狀態,假如activity的進程被殺掉了而你需要在activity重新建立時恢復fragment,你可以在fragment的onSaveInstanceState()回調方法中儲存狀態並且在onCreate()方法或是onCreateView()方法中恢復狀態。

activity的生命週期與fragment的生命週期之間最大的差異在於如何儲存在各自的back stack。預設,當activity停止會被置到由系統管理的back stack,然而,fragment只在你確切地要求在fragment移除時呼叫addToBackStack()方法儲存實例時,才會置入由寄主activity管理的back stack。

除此之外,管理fragment生命週期與管理activity生命週期非常類似,所以練習管理activity生命週期也可以用在fragment上,觀察activity生命週期如何影響fragment生命週期。


星期四, 11月 10, 2011

Fragment (八)

Android應用程式學習筆記

Communicating with the Activity

雖然fragment可以做為物件獨立於activity,也可以使用在多個activities,預設的fragment實體是直接與activity綁定。

特別是,fragment透過getActivity()方法可以存取Activity並輕鬆地執行工作比如取得activity布局的view。


View listView = getActivity().findViewById(R.id.list);

同樣地,你的activity也可以呼叫fragment中的方法,透過findFragmentById()方法或是findFragmentByTag()方法。


ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);


Creating event callbacks to the Activity

在一些情況中,你需要一個fragment與activity分享一個事件,在fragment定義一個回呼的介面並要求寄主activity執行是一個分享事件的好方法。當activity從界面接收到回呼,介面就會將資訊分享給在布局中的其他需要的fragment。

舉例,如果新聞應用程式有兩個fragment在activity中-一個顯示文章列表(Fragment A)-其他顯示文章內容(Fragment B),當一個列表選項被選到時,Fragment A必須告訴activity以便activity可以呼叫Fragment B去顯示文章內容,在此例中,OnArticleSelectedListener介面被宣告在Fragment A中。


public static class FragmentA extends ListFragment {
    ...
    // Container Activity must implement this interface
    public interface OnArticleSelectedListener {
        public void onArticleSelected(Uri articleUri);
    }
    ...
}

然後fragment的寄主activity執行OnArticleSelectedListener介面並複寫OnArticleSelected()方法,去通知Fragment B來自Fragment A的事件,為了確認寄主activity實現此介面,fragment A的onAttach()回呼方法將實體化OnArticleSelectedListener的Activity傳入onAttach()方法。


public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnArticleSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener");
        }
    }
    ...
}

如果activity沒有執行介面,fragment就會丟出ClassCastException例外,如果成功,mListener持有activity對OnArticleSelectedListener實現的引用,所以Fragment A可以通過呼叫由OnArticleSelectedListener介面定義的方法與Activity分享事件。例如,如果fragment A繼承ListFragment,每次用戶點擊列表項目,系統呼叫fragment中的onListItemClick()方法,接著在呼叫onArticleSelected()方法與Activity分享事件。


public static class FragmentA extends ListFragment {
    OnArticleSelectedListener mListener;
    ...
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Append the clicked item's row ID with the content provider Uri
        Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id);
        // Send the event and Uri to the host activity
        mListener.onArticleSelected(noteUri);
    }
    ...
}

傳入onListItemClick()方法中的id參數是被選的項目行ID,id用來從activity的ContentProvider取文章。

星期三, 11月 09, 2011

Fragment (七)

Android應用程式學習筆記

Managing Fragments

管理在你的activity的fragments,需要使用FragmentManager,從activtiy呼叫getFragmentManager()方法取得FragmentManager。

FragmentManager可以完成以下工作:

  • 取得存在於activity的fragment,findFragmentById()方法(有在activity布局中提供UI的fragment)或是findFragmentTag()方法(沒有在activity佈局中提供UI的fragment)。
  • 將fragment從back stack中拿出,popBackStack()方法。
  • 向back stack註冊一個監聽器,監聽改變,addBackStackChangedListener()方法。

Performing Fragment Transactions

在activity中與使用fragment有關的最重要議題就是增加、移除、替換及運用fragment執行其他工作,回應用戶的互動。你託付給activity的每一組fragment變化稱為一個transaction且你可以使用FragmentTransaction的APIs組織一個transaction。你可以將transaction存在back stack由activity管理,允許用戶反轉fragment變化。

你可以從FragmentManager獲得FragmentTransaction實例,像是這樣:

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
每個transaction都是你想在同意時間執行的變化組合,你可以使用比如add()、remove()、replace()方法組織所有你想要執行的變化為一個transaction,然後將transaction應用在activity上,最後你必須呼叫commit()方法。

在呼叫commit()方法之前,你可能想要呼叫addToBackStack()方法,為了增加transaction到fragment transaction的back stack。Back stack由activity管理且允許用戶按"BACK"按鈕回傳前一個fragment的狀態。

舉例,你如何將fragment由另一個fragment替換,並且將先前的狀態保存在back stack。

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
此例中,newFragment取代了目前在布局容器中ID為R.id.Fragment_container的fragment,藉由呼叫addToBackStack()方法,替換的transaction被存到back stack中,所以用戶可以反轉transaction並且透過"BACK"按鈕返回先前的fragment。

如果增加更多變化到transaction(比如其他add()、remove())並呼叫addToBackStack()方法,在呼叫commit()之前所有變化都會增加到back stack作為一個transaction且"BACK"可以將transaction一起反轉。

將變化加到FragmentTransaction的順序並不重要,除了:
  • 必須在最後時呼叫commit()方法。
  • 如果要增加多個fragment到同一個容器,加入的順序決定了出現在view階層的順序。
如果在執行transaction移除fragment時,沒有呼叫addToBackStack()方法,然後,transaction被commit,fragment被銷毀,用戶就無法在回去,反之,如果有呼叫addToBackStack()方法,fragment被停止,當用戶想回去時,fragment就會再次恢復。

呼叫commit()方法後並不會立即執行transaction,由activity的UI執行續安排。如果需要,可以從UI執行續呼叫executingPandingTransaction()方法立即執行transaction,並不是常常會如此需要,除非transaction牽涉到其他的執行續。



星期一, 11月 07, 2011

Fragment (六)

Android應用程式學習筆記

Adding a fragment without a UI

之前文章都是有關如何增加fragment到activity提供UI,然而,也可以使用fragment為activity提供後台行為,沒有額外的UI。

新增一個沒有UI的fragment,從activity利用add(fragment , String)方法(為fragment提供唯一的字串"Tag",-而不是view ID)增加fragment。這樣就新增了fragment,但是,因為不會牽涉到activity佈局中的View,就不用呼叫onCreateView(),所以你不需要實現此方法。

為fragment提供字串Tag並不限制在沒有UI的fragment-你也可以提供字串Tag給有UI的fragment,但是如果fragment沒有UI,那麼字串Tag是唯一能辨識他們的方式。如果你想從activity取得fragment,你需要利用findFragmentByTag()方法。


Fragment (五)

Android應用程式學習筆記

Adding a fragment to an activity

通常,fragment會貢獻一部份使用者介面在寄主activity,有兩種方式你可以將fragment增加到activity佈局上。
  • Declare the fragment inside the activity's layout file
    在此方法中,你可以設定fragment的屬性,以下舉例在activity的layout中增加兩個fragment。

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <fragment android:name="com.example.news.ArticleListFragment"
                android:id="@+id/list"
                android:layout_weight="1"
                android:layout_width="0dp"
                android:layout_height="match_parent" />
        <fragment android:name="com.example.news.ArticleReaderFragment"
                android:id="@+id/viewer"
                android:layout_weight="2"
                android:layout_width="0dp"
                android:layout_height="match_parent" />
    </LinearLayout>

    在<fragment>標籤範圍中的android:name屬性具體指定了在layout中實體化的Fragment類。
    當系統建立此activity布局時,它實體化佈局中的每個fragment並且呼叫每個fragment的onCreateView()方法去取得每個fragment的布局,系統將onCreateView()回傳的View直接插入<fragment>標籤的位置。
  • Or programmatically add the fragment to an existing ViewGroup
    在activity運行的任何時間,你可以增加fragment到你的activity布局,你需要指定fragment該置於哪個ViewGroup。在activity布局處理fragment的相關工作(比如新增、移除或是取代fragment),你必須使用FragmentTransaction,你可以從你的activity取得FragmentTransaction實例,如下。
  • FragmentManager fragmentManager = getFragmentManager()
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    你接著可以利用add()方法增加fragment,指定新增的fragment和插入fragment的View。
    ExampleFragment fragment = new ExampleFragment();
    fragmentTransaction.add(R.id.fragment_container, fragment);
    fragmentTransaction.commit();
    第一個傳入add()方法是fragment要置入的ViewGroup,由ID來表示,第二個參數是要置入ViewGroup的fragment。一旦你已在FragmentTransaction做了你的改變就必須呼叫commit()方法。

Fragment (四)

Android應用程式學習筆記

Adding a user interface

Fragment通常做為activity的使用者介面的一部份,且貢獻fragment自己的布局給activity。

要提供布局給fragment,你必須實現onCreateView()方法,當該是fragment繪製它的布局的時候,系統呼叫onCreateView()方法。此方法必須回傳一個View物件,該View物件為fragment布局的根節點。

如果你的fragment是ListFragment的子類,預設從onCreateView()回傳為一個ListView。

從onCreateView()回傳一個布局,你可以透過XML布局資源擴張布局,onCreateView()提供了LayoutInflater物件來幫助你擴張布局。

舉例,以下是一個Fragment的子類,從example_fragment.xml文件取得一個布局。


public static class ExampleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}

傳入onCreateView()的參數container是parent ViewGroup(來自activity的布局),你的fragment的布局將被放入ViewGroup中。參數savedInstanceState是一個Bundle物件,如果前一個fragment恢復,提供前一個fragment相關的數據。

inflate()方法有三個參數:
  • 你想擴張的布局的ID。
  • ViewGroup成為擴張布局的parent。
  • 布林值是要表示擴張的布局是否要在擴張時依附在ViewGroup上(在此例中,布林值為fales是因為系統正準備將擴張的布局插入container中-傳入true將在布局最後建立重複的view group)。

Fragment (三)

Android應用程式學習筆記

Creating a Fragment

建立Fragment,必須建立Fragment的子類,Fragment類有很多和Activity類很像的方法,包括回調方法,比如,onCreate()、onStart()、onPause()和onStop()。事實上,如果你正在將已存在的Android應用程式轉換成使用Fragment,你可能能輕鬆地將程式碼從Activity的回調方法移到fragment對應的回調方法中。

通常,你至少應該執行以下的生命週期方法:
onCreate()
當建立fragment時系統呼叫此方法。在方法中,應該為重要的組件完成初始化的動作。
onCreateView()
當輪到fragment繪製自己的使用者介面的時候,系統呼叫此方法。為你的fragment繪製使用者介面,你必須從此方法回傳一個View物件,View物件是你的fragment布局的根結點,如果你的fragment沒有提供使用者介面,你可以回傳null。
onPause()
系統呼叫此方法作為用戶離開fragment的第一個提示。此方法通常是承擔任何改變的地方,應該保持超過目前用戶使用期間(因為用戶可能不會再回來)。
大部分的應用程式都應該至少為每個fragment實現這三個方法,但是也有許多其他回調方法可以使用來處理不同階段的生命週期。

也有一些子類你可以繼承,取代Fragment類:

DialogFragment
顯示一個浮動對話框,比起使用Activity類中的對話框輔助方法,使用此類建立對話框是一個好選擇。因為你可以將fragment對話框併入由activity管理的fragment的back stack。
ListFragment
顯示一列由適配器管理的項目列表,類似ListActivity,它提供許多方法管ListView,比如,onListItemClick()回調方法來處理click事件。
PreferenceFragment
類似PrefereneceActivity,顯示Preference物件的階層如列表。

星期五, 11月 04, 2011

實作並觀察Activity生命週期

Android應用程式學習筆記

實作說明: 試著觀察生命週期。我們運行兩個activity,並複寫所有生命週期中的回調方法,通過activity A啟動activity B和activity B啟動activity A觀察兩個activity的生命週期變化。

Activity A(HelloActivityActivity):


  1. package test.activity;

  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.Button;

  7. public class HelloActivityActivity extends Activity {
  8.     /** Called when the activity is first created. */
  9. private Button mBtn;
  10.     @Override
  11.     public void onCreate(Bundle savedInstanceState) {
  12.      //初始化所有成員變數
  13.         super.onCreate(savedInstanceState);
  14.         setContentView(R.layout.main);
  15.         System.out.println("Activity1---onCreate");
  16.         mBtn = (Button)findViewById(R.id.button1);
  17.     }

  18.     public void GoToActivity2(View view){
  19.      Intent intent = new Intent(HelloActivityActivity.this , activity2.class);
  20.      startActivity(intent);
  21.     }
  22. @Override
  23. protected void onDestroy() {
  24. // TODO Auto-generated method stub
  25. //釋放所有資源
  26. super.onDestroy();
  27. System.out.println("Activity1---onDestory");
  28. }

  29. @Override
  30. protected void onPause() {
  31. // TODO Auto-generated method stub
  32. //此方法執行後,activity失去用戶焦點,
  33. super.onPause();
  34. System.out.println("Activity1---onPause");
  35. }

  36. @Override
  37. protected void onRestart() {
  38. // TODO Auto-generated method stub
  39. super.onRestart();
  40. System.out.println("Activity1---onRestart");
  41. }

  42. @Override
  43. protected void onResume() {
  44. // TODO Auto-generated method stub
  45. //此方法執行後,activity取得用戶焦點,
  46. super.onResume();
  47. System.out.println("Activity1---onResume");
  48. }

  49. @Override
  50. protected void onStart() {
  51. // TODO Auto-generated method stub
  52. //此方法執行後,用戶看的見activity,置方法監控影響UI的事件,隨時隨環境變化UI
  53. super.onStart();
  54. System.out.println("Activity1---onStart");
  55. }

  56. @Override
  57. protected void onStop() {
  58. // TODO Auto-generated method stub
  59. //此方法執行後,用戶無法看見activity,釋放所有在onStart()所有監控影響UI的方法
  60. super.onStop();
  61. System.out.println("Activity1---onStop");
  62. }
  63.     
  64. }
Activity B(activity2):
  1. package test.activity;

  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.widget.Button;

  7. public class activity2 extends Activity {
  8. private Button mBtn; 

  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. // TODO Auto-generated method stub
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.layout2);
  14. System.out.println("activity2---onCreate");
  15. mBtn = (Button)findViewById(R.id.button1);
  16. }
  17. public void BackToActivity1(View view){
  18. Intent intent = new Intent(activity2.this , HelloActivityActivity.class);
  19. startActivity(intent);
  20. }

  21. @Override
  22. protected void onDestroy() {
  23. // TODO Auto-generated method stub
  24. super.onDestroy();
  25. System.out.println("activity2---onDestory");
  26. }

  27. @Override
  28. protected void onPause() {
  29. // TODO Auto-generated method stub
  30. super.onPause();
  31. System.out.println("activtiy2---onPause");
  32. }

  33. @Override
  34. protected void onRestart() {
  35. // TODO Auto-generated method stub
  36. super.onRestart();
  37. System.out.println("activity2---onRestart");
  38. }

  39. @Override
  40. protected void onResume() {
  41. // TODO Auto-generated method stub
  42. super.onResume();
  43. System.out.println("activity2---onResume");
  44. }

  45. @Override
  46. protected void onStart() {
  47. // TODO Auto-generated method stub
  48. super.onStart();
  49. System.out.println("activity2---onStart");
  50. }

  51. @Override
  52. protected void onStop() {
  53. // TODO Auto-generated method stub
  54. super.onStop();
  55. System.out.println("activity2---onStop");
  56. }


  57. }

實驗一:執行activity A後關閉,觀察生命週期變化。
變化如下圖。

發現一個activity開始運行到出現在屏幕上會經過生命週期為onCreate()->onStart()->onResume(),關閉activity會經過生命週期為onPause()->onStop()->onDestory()。
實驗二:執行activity A後,A啟動activity  B,B再啟動A,接著按"BACK"直到結束整個activity,觀察生命週期變化。
變化如下圖。
觀察activity A啟動時會經過生命週期onCreate()->onStart()->onResume(),A啟動activity B會經過生命週期就比較複雜,首先要啟動B,A會先onPause(),接著換B要運行了,B會執行onCreate()->onStart()->onResume(),B取得用戶焦點,因此,A執行onStop()。執行到此我們來想想task狀態,task目前總共放有兩個activity,下層是最先執行的A,頂層是從A啟動的B,而從B啟動的A正在執行。現在接著按"BACK"按鈕,觀察A先執行onPause()讓在task頂層的B恢復,B執行onRestart()->onStart()->onResume(),A執行onStop()->onDedtory(),A結束,再按一次"BACK"按鈕,觀察B一樣先執行onPause()讓task中剩下的A恢復,A執行onRestart()->onStart()->onResume(),B執行onStop()->onDestory(),B結束,再按一次"BACK"按鈕,應用程式關閉,A執行onPause()->onStop()->onDestory(),A結束。


星期四, 11月 03, 2011

SQLiteOpenHelper

Android應用程式學習筆記

SQLiteOpenHelper

主要功能用於管理資料庫創建與版本的helper類。

此類實現了onCreate(SQLiteDatabase)、onUpgrate(SQLiteDatabase , int , int ),並可以選擇性地實現onOpen(SQliteDatabase),如果資料庫不存在,回呼onCreate(SQLiteDatabase)方法建立資料庫;如果版本不同或需要更新,回呼onUpgrade(SQLiteDatabase , int , int )方法資料庫升級;如果資料庫存在,回呼onOpen(SQLiteDatabase)打開資料庫。

此類別可以使ContentProvider容易地實現,避免阻塞應用程式開啟時資料庫要長時間更新。

它有兩種建構式:

public SQLiteOpenHelper(Context context , String name , SQLiteDatabase.CursorFactory factory , int version)
建立Helper物件來建立、打開、管理資料庫,此方法回傳很快,資料庫直到呼叫getWritableDatabase()或是getReadableDatabase()才會建立或是打開。  
參數: context-使用打開或是建立資料庫;name-資料庫名稱;factory-用來建立cursor物件,null表示為使用預設;version-資料庫版本,通常從1開始。如果版本太舊,呼叫onUpgrade(SQLiteDataBase , int , int )更新資料庫,如果版本太新,呼叫onDwongrade(SQLiteDatabase ,int ,int)更新資料庫。


此類實現的方法:
public void close()
關閉任何開啟的資料庫。
public SQLiteDatabase getReadableDatabase()
建立且/或開啟資料庫,回傳唯讀的資料庫。 
如getWritableDatabase()方法,此方法可能花較長的時間才會回傳,所以你不應該在應用程式的主執行續中呼叫,應該從ContentProvider.onCreate()。
returns: 回傳一個資料庫物件,直到getWritableDatabase()或是close()呼叫時才變成無效。
throws: 如果無法開啟時丟出SQLiteException例外。 
public SQLiteReadableDatabase()
建立且/或讀及寫的資料庫,第一次呼叫此方法,資料庫被開啟並且呼叫onCreate(SQLiteDatabase)、onUpgrade(SQLiteDatabase , int , int )方法,選擇性地呼叫onOpen(SQLiteDatabase)方法。
更新資料庫可能要花較長時間,你不應該在應用程式主執行續中呼叫此方法,應該從ContentProvider.onCreate()。
returns: 回傳資料庫物件 ,直到close()方法呼叫時才無效。
throws: 如果無法寫入資料庫,丟出例外SQLiteException。 
 public void onCreate(SQLiteDatabase db)
當資料庫第一次被建立時呼叫此方法,建立資料表的地方。
參數: db資料庫。 
public void onUpgrade(SQLiteDatabase db , int oldVersion , int newVersion)
資料庫升級時呼叫此方法,應該利用此方法實現摘除資料表、新增資料表或任何升級需要的工作。 

星期二, 11月 01, 2011

Fragment (二)

Android應用程式學習筆記

Design Philosophy

Android在Android 3.0介紹fragment,主要在更大的屏幕支援更動態及彈性的使用者介面設計,比如平板電腦,因為平板電腦的屏幕比手持的更大,有更多空間綁定及交換使用者介面組件,像fragment的設計允許你不需要管理複雜的視圖階層樹,藉著切割activity的布局成fragments,你變成可以在activity運行時修改activity的外觀,並且將變動保存在由activity管理的back stack中。

例如,有一個新的應用程式利用一個fragment在左邊顯示文章的列表,其他fragment在右邊顯示文章內容-兩個 fragment肩並肩地出現在同一個activity,且每個fragment都擁有自己一組生命週期回調方法來處理它們用戶輸入自己的事件。因此,取代一個activity用來選擇文章,另一個activtiy顯示文章內容,用戶可以在同一個activtiy中選擇文章及閱讀文章,見圖1。


你應該設計fragment為一個模件且可以在activity組件中重複使用,那是因為每個fragment在自己的生命周期回調方法定義了自己的布局及自己的行為,你可以在多個activity中包含同一fragment,所以你應該涉及能重複使用且避免直接從其他fragment操作fragment,這特別重要,因為模件的fragment允許你在不同大小的屏幕中改變fragment的組合。當你設計應用程式支援平板電腦及手持的裝置,你可以基於可用的屏幕空間中在不同布局配置中重複使用fragment來最佳化用戶使用經驗。例如,當無法將fragment塞入手持裝置屏幕,就必須分割fragment。