編輯:關於Android編程
一個Fragment的實例總是和包含它的Activity直接相關。
fragment可以通過getActivity()
方法來獲得Activity的實例,然後就可以調用一些例如findViewById()之類的方法。
如:
View listView = getActivity().findViewById(R.id.list);
但是注意調用getActivity()時,fragment必須和activity關聯(attached to an activity),否則將會返回一個null。
相似的,activity也可以獲得一個fragment的引用,從而調用fragment中的方法。
獲得fragment的引用要用FragmentManager,之後可以調用findFragmentById()
或者 findFragmentByTag()
.
比如:
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
一些情況下,可能需要fragment和activity共享事件,一個比較好的做法是在fragment裡面定義一個回調接口,然後要求宿主activity實現它。
當activity通過這個接口接收到一個回調,它可以同布局中的其他fragment分享這個信息。
例如,一個新聞顯示應用在一個activity中有兩個fragment,一個fragment A顯示文章題目的列表,一個fragment B顯示文章。
所以當一個文章被選擇的時候,fragment A必須通知activity,然後activity通知fragment B,讓它顯示這篇文章。
這個情況下,在fragment A中聲明一個這樣的接口OnArticleSelectedListener:
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 A中發生的事通知fragment B。
為了確保宿主activity實現這個接口,fragment A的onAttach()
方法(這個方法在fragment
被加入到activity中時由系統調用)中通過將傳入的activity強制類型轉換,實例化一個OnArticleSelectedListener對象:
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接口的一個引用,所以通過調用OnArticleSelectedListener接口的方法,fragment A可以和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); } ... }
三種停留狀態
管理fragment的生命周期和管理activity的生命周期類似,和activity一樣,fragment可以在三種狀態下停留:
Resumed
fragment在running的activity中可見。
Paused
另一個activity在前景運行,並且享有焦點,但是這個fragment所在的activity仍然可見(前景activity部分遮擋或者是半透明的)。
Stopped
fragment不可見。可能是因為宿主activity處於stopped狀態,或者fragment被remove掉,然後加在了back stack中。
一個處於stopped狀態的activity還是存活狀態的,所有的狀態和成員信息會被系統保持。但是,它不再被用戶可見,並且如果宿主activity被kill掉,它也會被kill掉。
數據存儲和恢復
和Activity類似,可以用Bundle類對象保存fragment的狀態,當activity的進程被kill之後,需要重建activity時,可以用於恢復fragment的狀態。
存儲時利用onSaveInstanceState()回調函數,恢復時是在 onCreate()
, onCreateView()
,
或者onActivityCreated()
裡。
Back Stack
activity和fragment生命周期最重要的不同之處是它們如何存儲在各自的back stack中。
Activity停止時,是存在一個由系統維護的back stack中,但是當fragment停止(被remove)時,需要程序員顯示地調用addToBackStack()
,並且fragment是存在一個由宿主activity掌管的back
stack中。
Fragment和Activity的生命周期
宿主activity的聲明周期直接影響到fragment的生命周期,比如activity生命周期的回調函數調用時,所有在其中的fragment的相同的回調函數會同時被調用。
Fragment還有一些額外的生命周期回調函數:
onAttach()
當fragment和activity被關聯時調用。
onCreateView()
當創建fragment的UI被初始化時調用。
onActivityCreated()
當activity的onCreate()方法返回時調用。
onDestroyView()
當fragment的UI被移除的時候調用。
onDetach()
當fragment和activity去關聯時調用。
如圖:
從這個圖上可以看出activity的狀態決定了fragment可能接收到的回調函數。
比如說,當activity接收到它的onCreate()回調函數,那麼這個activity中的fragment最多接收到了onActivityCreated()。
當activity處於Resumed狀態時,可以自由地添加和移除fragment,也即是說,只有activity在Resumed狀態時,fragment的狀態可以獨立改變。
但是,當activity離開Resumed狀態,fragment的生命周期被activity控制。
市面上有好多的類比ListView刷新數據的開源框架,如:v4包自帶的SwipeRefreshLayout ,以及集ListView、GridView甚至WebView於
把github上的PagerSlidingTabStrip稍作修改: tab的文字顏色選中變色(原版文字不變色) 栗子:http://download.csdn.ne
最近幾個項目的測試結果,Android無法主動通過調用 webview.loadUrl(javascript:+callbackFunction+(+data+)); 這
前言本篇博客主要記錄NDK開發之入門小demo,雖說NDK開發包裡面有hellojni的項目,但是博主還是記錄一下學習的過程吧.AS2.2現在對NDK支持的已經很好了,但