转载请注明出处:http://blog.csdn.net/zhouli_csdn/article/details/45558719
fragment嵌入在activity中使用,它有自己的生命周期,接收它自己的输入事件。但是它的生命周期受到宿主activity的直接影响,当activity执行pause,fragment也会,destroy时也一样。在acitivity运行时,你可以动态的添加或者删除fragment,同时你可以把它添加进管理它的activity的返回栈中(activity的每一个返回栈节点都是一个发生的fragment记录),返回栈允许用户通过返回键返回。
activity存活于activity的viewgroup中,你可以在activity的layout文件中声明一个fragment或者在代码中动态的向一个已知的viewgroup中添加。然而,fragment不是必须成为activity的一部分layout,你可以使用一个没有UI的invisible的fragment作为activity的工作者。
本文会讲诉如何在activity中使用fragment,fragment在添加进返回栈中是如何保存状态的,和activity以及其它fragment分享一些events,对actionBar一些帮助等等。
设计理念(Design Philosophy)
创建一个fragment
如果你希望使用fragment,你可以简单的将activity中回调方法的代码移到对应的fragment中。你需要实现至少以下方法:
oncreate:当创建fragment的时候,系统会调用此方法。你可以在这里初始化一些基本的组件(那些你想在fragment暂停或者停止之后又resume)
onCreateView:当fragment第一次绘制自己的Ui的时候,系统会调用此方法。你可以返回一个将作为fragment根layout的view或者返回null.
onPause:通常在这里你应该提交一些改变,保存在用户当前回话中。
fragment的一些子类:
DialogFragment:显示一个浮动对话框。比使用dialog好,因为允许添加到堆栈可以返回到之前的fragment。
ListFragment:通过adapter管理一些子条目相当于listview。onCreateView方法默认返回一个listview,不必实现此方法。
PreferenceFragment:类似于PreferenceActivity,用来为应用创建一个settings。
通过inflater.inflate(R.layout.example_fragment, container, false);返回一个view给fragment,inflate有三个参数:
1.你想绘制的layout的id
2.是要绘制的layout的parent,系统会将layout parameters给要绘制的view的根。
3.是否将要inflate的layout添加进参数2中。(在这里为false,因为系统已经将它添加进去了,如果为true,将会创建一个冗余的viewgroup)。
在activity的layout文件中声明fragment:
注意:每一个fragment必须包含一个标识,如果activity发生restarted系统用来恢复fragment,并且你可以用来对fragment进行操作(例如删除)。三种方法添加标识:
1.提供一个id 2.提供android:tag用一个唯一的字符串3.如果前两者都没有系统会使用参数2 的id。
在代码中添加fragment:
使用FragmentTransaction:add,remove,replace操作,之后必须commit使变化生效。
添加一个没有UI的fragment:
使用add(Fragment,String)方法添加一个fragment(提供一个tag而不是id),因为没有和activity的layout中的view关联,多以不会调用onCreateView方法,可以使用findFragmentBytag方法找到fragment。
管理fragments
使用fetFragmentManager获得FragmentManager.你可以做以下动作:
1.获得在activity中的fragment(findFragmentById(提供了UI)或者findFragmentBytag(没有提供UI)))
2.使用popBackStack从返回栈弹出fragment,类似用户执行返回键
3.注册一个监听器addOnBackStackChangeListener,监听返回栈的变化。
4.其它操作,例如beginFragmentTransaction。
你可以在一个transaction中执行多个add,remove,replace操作,然后添加进返回栈中,然后返回键将会一起恢复它们。
当你在执行一个transaction的remove操作的时候,调用了addToBackStack方法,这个fragment被stoped,的用户返回时它会resume。如果没有addToBackStack,那么这个fragment会被销毁。
调用commit并不会立刻执行transaction,而是在调度UI线程的时候。当然你可以在UI线程调用executePendingtransactions使立即实行。通常你不必做这个,除非这个transaction依赖与其它线程。
警告:你必须在activity保存它的状态之前commit,如果你在这之后提交会抛出异常。因为这样做,提交的状态会丢失,如果你允许丢失,你可以使用commitAllowingStateLoss。
与activity交互
fragment中可以使用getActivity,activity中可以使用getFragmentManager().findFragmentById(R.id.example_fragment)
一些情况你需要fragment分享一些事件给activity。
例如:Aactivity可以定义一个监听接口,然后在fragment的onAttach方法中初始化一个监听对象。例如:
@Override public void onAttach(Activity activity) { super.onAttach(activity); try { mListener = (OnArticleSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnArticleSelectedListener"); } }
// Container Activity must implement this interface public interface OnArticleSelectedListener { public void onArticleSelected(Uri articleUri); }
将条目添加到操作栏
略:
注意:尽管fragment接收到onItemselected回调方法,activity最先接受到这个方法,如果activity的这个没有处理它,然后才会将这个事件传递给fragment的回调方法。这同样适用于Options Menu and context menus.
处理Fragment生命周期
和activity的生命周期一样
resume:在运行的activity中可见时
paused:另外一个activity在它之上,但是它的宿主仍然有一部分可见
stopped:activity暂停,或者fragment被remove但是被添加进返回栈。activity如果被杀死,fragment也会被杀死。
你可以适用bundle保存fragment的状态以防activity的进程被杀死。你可以在onSaveInstanceState方法保存fragment的状态,然后在onCreate或者onCreateView,或者onActivityCreated方法中恢复。
它和activity最重要的区别在于返回栈。activity保存与系统管理的返回栈中,fragment保存在activity管理的返回栈中。
注意:当fragment没有被绑定到activity(onAttach)或者解除绑定到activity(onDetach),getActivity会返回null.
与activity协调的生命周期
activity每一个生命周期的发生都会导致它的每一个fragment对应的生命周期的发生。它有一个其它的生命周期方法:
onAttach:fragment和activity关联时调用,activity会被传递。
onCreateView:用来返回fragment的view
onActivityCreated:activity的onCreate方法返回时被调用
onDestroyView:当和fragment关联的view被removed时调用
onDetach:当fragment和activity解除关联时被调用
fragment的生命周期不会超过activity的生命周期调用。例如:activity调用onCreate,那么fragment只会调用到onActivityCreated。只有当activity处于onResume状态时,你可以自由的添加和删除fragment,这时候fragment的生命周期独立的改变。
布局方向:res/layout-land/fragment_layout.xml 横屏布局
res/layout/fragment_layout.xml竖屏布局