Android學習筆記11——使用者介面之Fragments(3)
如何管理我們的Fagment呢?
為了管理我們Activity中的Fragments,我們需要用到FragmentManager。我們可以在我們的Activity中調用getFragmentManager()方法來得到這個FragmentManager這個對象。
我們可以使用FragmentManager做一下幾件事情:
1、我們可以用findFragmentById或者findFragmentByTag方法擷取到Activity中的fragments;
2、可以用popBackStack方法來類比使用者的回退按鈕操作,從回退棧中中彈出fragments;
3、用addOnBackStackChangedListener()方法為回退棧的改變註冊一個監聽器。
如何進行Fragment的交易處理呢?
在我們的Activity中使用fragment的一個優點是我們可以用他們動態添加、移除、替換和表現一些其他的動作來相應使用者的互動。我們的每一把這樣的改變提交給Activity成為一個事務。我們也可以把每一個fragment儲存到activity所管理的回退棧中,這樣就會使得使用者回退這些fragment的改變。
ragmentManager fragmentManager = getFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
每一次事務是同時進行的你想進行的一系列的改變。我們可以設定我們想要進行的所有改變操作用一個被給予的Transaction對象,然後如果我們想要把這些改變應用到activity中,我們必須調用commit()方法。
然而,可能在我們調用commit方法之前,為了把這次事務添加到fragment的回退棧中,我們可能想要調用addToBackStack方法。這個回退棧被這個fragment所在的Activity管理,允許使用者可以通過回退按鈕返回到上一個fragment狀態。
// Create new fragment and transactionFragment 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 stacktransaction.replace(R.id.fragment_container, newFragment);transaction.addToBackStack(null);// Commit the transactiontransaction.commit();
如果我們一次提交事務多個改變,並且調用了addToBackStack方法把所有的改變當作一次事務儲存到回退棧中,那麼我們點擊回退按鈕時將會一次性恢複多個改變。
我們添加這些改變到FragmentTransaction的順序是無關緊要的,除了兩種情況:第一種是我們必須最後調用commit方法;第二種是如果我們添加多個fragments到相同的容器中,我們添加的fragment的順序決定了他們在視圖成次顯示的順序。
當時如果我們在進行移除fragment事務的時候沒有調用addToBackStack方法,這個fragment在我們提交的時候會被銷毀掉,並且使用者也不能返回到這個fragment。
注意:我們可以在每一次事務提交commit方法之前調用setTransition方法來設定一個事務動畫。
調用commit方法並不能立即執行這些事務。相反,這些事務是在Activity的UI線程中執行的,當這個UI線程能夠執行這些事務的時候。然而,如果有需要,我們可以調用executePendingTransaction方法使得我們的Activity的UI線程能夠立即執行這些提交的事務。但是盡量不要這樣做,除非這個事務是獨立於其他線程中的工作的,這可能中斷其他工作。
Fragment與Activity之間是如何通訊的呢?
儘管Fragment被作為獨立於Activity的一個對象來實現,能夠被應用在多個Activity中,並且一個被給予的fragment執行個體能夠直接綁定到包含它的Activity中。
在特殊的時候,我們可以在fragment中調用getActivity方法訪問到Activity執行個體,很容易進行一些操作,例如獲得到activity布局中的一個視圖組件。
View listView = getActivity().findViewById(R.id.list);
同樣的,我們的Activity中也可以通過FragmentManager中的Fragment的引用調用fragment中的方法。例如
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
建立activity的事件回呼函數
在某些情況下,我們可能需要一個fragment和
例如,如果在一個Activity中有兩個fragement,一個展示文章列表A,一個展示文章詳情B。當使用者選中文章中的一項時fragment A必須告訴這個Activity,然後這個Activity在通知fragment B 去在展示文章。
public static class FragmentA extends ListFragment { ... // Container Activity must implement this interface public interface OnArticleSelectedListener { public void onArticleSelected(Uri articleUri); } ...}然後操作這個Fragment的Activity實現OnArticleSelectedListener介面並且重載onArticleSelected方法通知fragmentB 在fragmentA中發生的事件。為了確保這個主Activity實現這個介面,在Fragment A中的onAttach方法中的activity參數轉為OnArticleSelected來執行個體化一個OnArticleSelected執行個體。
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沒有實現這個介面,在上面這個方法中就會拋出一個ClassCastException。如果成功的話,mListener就會擁有OnArticleSelectedListener介面在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); } ...}