16.fragment与activity交互方式?
15.fragment保存数据?
14.Fragment的事务 与 fragment的回退栈?
13.给Fragment设置参数?
12.对于Fragment的一些操作对生命周期的影响
11.fragment生命周期:
======
15.fragment保存数据?
与Activity类似,你可以利用Bundle来记录Fragment的状态,当Activity被销毁需要记录Fragment状态,并且在Activity重新创建的时候恢复Fragment的状态。
你可以保存Fragment的状态在Fragment的onSaveInstanceState()回调方法中,在onCteate()、onCreateView()或者onActivityCreated()方法中进行恢复。
但是因为Fragment依附于Activity。
所以,关于Fragment创建的生命周期总是在Activity之后调用,关于Fragment销毁的生命周期总是在Activity之前调用。
除此之外,在Activity需要重新创建的时候,fragment和activity一样可以通过onSaveInstanceState来保存状态,然后在onCreate,onCreateView或者onActivityCreated期间恢复状态。
注意:在Fragment中你如果要获取一个Context对象,你可以调用getActivity()方法,但是调用getActivity()方法必须要在Fragment于Activity关联起来之后,否则getActivity()返回为null。
14.Fragment的事务 及 fragment的回退栈?
FragmentTransaction也就是fragment的事务,这对我们理解生命周期有很重要的作用。
那么什么是事务?
根据用户的交互情况, 对fragment进行添加(add)、移除(remove)、替换(replace),以及执行其他动作,提交给activity的每一套变化,被称为一个事务。
事务当中存在一个堆栈的数据结构,它允许用户经由fragment的变化往回导航(就是和activity回跳类似,这和activity之间跳转实现都是一样的,均用堆栈实现)。
用户可以通过添加FragmentTransaction.addToBackStack(null)函数(一定要在FragmentTrasaction.commit()之前调用),将此Fragment添加到后台堆栈。
在生命周期中Activity与Fragment的最大不同之处是回退栈是相互独立的,Activity的回退栈是系统来管理的,Fragment的回退栈是被宿主Activity来管理的,也就是说你可以来进行控制(调用addToBackStack()).
13.给Fragment设置参数
使用setArguments,在创建Fragment的时候传递参数,然后在fragment的onCreate方法处获取参数,但是需要注意的是setArguments()方法必须在fragment创建以后,add之前调用。这样的好处是对Fragment的代码进行管理
//流行一种做法是使用静态方法newInstance()的方式来初始化Fragment
public static CircleFragmetn newInstance(String str){
Bundle bundle = new Bundle();
bundle.putString("data", str);
CircleFragmetn fragment = new CircleFragmetn();
fragment.setArguments(bundle);
return fragment;
}
没有UI的Fragment
可以添加没有UI的Fragment,使用add(Fragment,String)向Activity添加片段,由于它不与Activity布局的视图关联,所以不会触发onCreateView。通常没有UI的Fragment都是用于保存Activity的状态,或者借助setTargetFragment来控制其他fragment的UI变化,使用setRetainInstance()这个方法来告诉框架,当配置发生改变的时候,尝试保留这个fragment。
12.对于Fragment的一些操作对生命周期的影响
// replace,FragmentA替换为FragmentB,在创建完B以后会先销毁A,再创建B的视图
FragmentB: onAttach
FragmentB: onCreate
——————————————————————————
FragmentA: onPause
FragmentA: onStop
FragmentA: onDestroyView
FragmentA: onDestroy
FragmentA: onDetach
——————————————————————————
FragmentB: onCreateView
FragmentB: onActivityCreated
FragmentB: onStart
FragmentB: onResume
// add,添加FragmentA
FragmentA: onAttach
FragmentA: onCreate
FragmentA: onCreateView
FragmentA: onActivityCreated
FragmentA: onStart
FragmentA: onResume
//remove,移除FragmentA
FragmentA: onPause
FragmentA: onStop
FragmentA: onDestroyView
FragmentA: onDestroy
FragmentA: onDetach
//attach,从detach到attach状态
FragmentA: onCreateView
FragmentA: onActivityCreated
FragmentA: onStart
FragmentA: onResume
//detach,从attach到detach状态
FragmentA: onPause
FragmentA: onStop
FragmentA: onDestroyView
注意:hide和show不会触发生命周期回调
11.fragment生命周期?及案例?
Fragment必须是依存于Activity而存在的。因此,Activity的生命周期会直接影响到Fragment的生命周期。
onAttach()
onCreate()
onCreateView()
onActivityCreated()
onStart()
onResume()
onPause()
onStop()
onDestroyView()
onDestroy()
onDetach()
注意:除了onCreateView,其他所有的方法如果你重写了,必须要调用父类对于该方法的实现。
-----
void onAttach(Context context)//当Activity与Fragment发生关联时调用
这个方法是在fragment与activity关联之后调用,我们能在这个方法中获取这个关联的activity的实例。
但是当你的sdk更新到android6.0(api-23)是就会显示这个方法是过时的,使用onAttach(Context context)这个方法代替,但在看fragment的生命周期时,这个方法好像不调用,所以你获取的Context是null
他只调用一次。
void onCreate(Bundle savedInstanceState) //fragment初始化的时候调用,
//通过getActivity() 获取Activity的上下文。
我们通常在这个方法使用getArgument获取activity传来初始化fragment的参数。
注意:在这个方法中我们不能获取activity中控件,下面代码是在fragment的onCreate中的,你发现activity不是空,但是text是null。
因为,这是activity的onCreate还没有执行完,即activity还没有创建完,要想获取activity相关的资源应该在onActivityCreated中获取。
MainActivity activity=(MainActivity) getActivity();//activity不是null
TextView text=activity.findViewById(R.id.textview);//text是null
系统创建fragment的时候回调他,在他里面实例化一些变量,这些个变量主要是:当你暂停 停止的时候,你想保持的数据。
如果我们要为fragment启动一个后台线程,可以考虑将代码放于此处。
参数是:Bundle savedInstance, 用于保存Fragment参数, Fragement也可以重写 onSaveInstanceState(BundleoutState) 方法, 保存Fragement状态;
可以用于 文件保护 。
他只调用一次。
View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)
//创建该Fragment的视图返回Fragment的布局
主要是通过布局填充器获取fragment布局。通过view.findViewById初始化fragment中的控件,
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view=inflater.inflate(R.layout.text_content, null);
text=(TextView) view.findViewById(R.id.textview);
return view;
第一次使用的时候 fragment会在这上面画一个layout出来,为了可以画控件 要返回一个 布局的view,也可以返回null;
当系统用到fragment的时候 fragment就要返回他的view,越快越好,所以尽量在这里不要做耗时操作,比如从数据库加载大量数据显示listview,当然线程还是可以的。
给当前的fragment绘制ui布局,可以使用线程更新UI。说白了就是加载fragment的布局的。
这里一般都先判断是否为null
if(text==null){
Bundle args=getArguments();
text=args.getString("text");
}
if (view == null) {
view = inflater.inflate(R.layout.hello, null);
}
这样进行各判断省得每次都要加载,减少资源消耗。
当需要创建一个与Fragment关联的View时候会调用,这个方法会返回一个View,这个View会被添加到Activity的View树中,如果你不想Fragment显示一个View就返回null。
void onActivityCreated(@Nullable Bundle savedInstanceState); //当Activity中的onCreate()方法执行完后调用。
方法是在activity的onCreate方法执行完执行这个方法,通知fragment,关联的activity的onCreate方法执行完了,即activity创建完了,可以在这个方法中获取activity中的资源。
例如下面,可以获取activity布局中的TextView控件
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView text=getActivity().findViewById(R.id.textview);//获取activity布局中的TextView控件
}
注意了:从这句官方的话可以看出:当执行onActivityCreated()的时候 activity的onCreate才刚完成。
所以在onActivityCreated()调用之前 activity的onCreate可能还没有完成,所以不能再onCreateView()中进行 与activity有交互的UI操作,UI交互操作可以砸onActivityCreated()里面进行。
所以呢:这个方法主要是初始化那些你需要你的父Activity或者Fragment的UI已经被完整初始化才能初始化的元素。
如果在onCreateView里面初始化空间 会慢很多,比如listview等
void onStart()//在Activity的onStart之后调用,此时Fragement可见;
是在activity的onstart执行完立即执行,这个方法执行完fragment界面就显示出来,但是现在还没有获取焦点,用户是不能操作。
void onResume()//在Activity的onResume之后立即执行,此时fragment的获取了界面,用户可以操作。
Fragment的运行状态,此时Fragment处于运行状态,并且可以与用户之间进行交互;
在activity中运行是可见的;
激活, Fragement 进入前台, 可获取焦点时激活;
void onPause() //执行完后,立即执行activity的onPause方法
fragment失去焦点,此时用户是不能操作的,执行完立即执行activity的onPause方法。
和activity一致,其他的activity获得焦点,这个仍然可见,
第一次调用的时候,指的是用户 离开这个fragment(并不是被销毁),通常用于用户的提交(可能用户离开后不会回来了)。
有其他Activity获取焦点,前台运行,Fragment所在的Activity失去焦点,部分的显示在前台Activity下面。
void onStop()//fragment不可见,执行完立即执行activity的onStop方法。
和activity一致fragment不可见的, 可能情况:activity被stopped了 Or fragment被移除但被加入到回退栈中。
一个stopped的fragment仍然是活着的,如果长时间不用也会被移除。
Fragment不再可见,此时的情形可能是Fragment所在的Activity已经stopped了,或者fragment从Activity中移除到Fragment回退栈中。
一个Stopped状态的Fragment没有被销毁,还在存活状态,它的状态和内部信息被系统记录和保存,只是不可见,不可交互,此时很可能会被系统回收。
void onDestroyView() ;//与onCreateView相对应,当该Fragment被移除时调用
在onCreateView中创建的fragment视图会被销毁。Fragment的视图被回收。
当与Fragment关联的那个View(在onCreatView()方法中创建的)与Fragment解除关联,从View树中移除的时候调用,在下次Fragment需要显示一个View的时候会重新调用onCreatView方法。
Fragment中的布局被移除时调用。
表示fragemnt销毁相关联的UI布局,清除所有跟视图相关的资源。
以前以为这里没什么用处其实 大有文章可做,
相信大家都用过ViewPager+Fragment,由于ViewPager的缓存机制,每次都会加载3页。
例如:有四个 fragment 当滑动到第四页的时候,第一页执行onDestroyView(),但没有执行onDestroy。他依然和activity关联。
当在滑动到第一页的时候又执行了 onCreateView()。 生命周期可以自己试一下。
那么问题来了。会出现重复加载view的局面,所以这么做;
@Override
public void onDestroyView() {
if(view!=null){
((ViewGroup)view.getParent()).removeView(view);
}
super.onDestroyView();
}
void onDestroy() //销毁fragment对象,在Activity的onDestroy之前调用;
当这个fragment不再使用时调用。需要注意的是,它即使经过了onDestroy()阶段,但仍然能从Activity中找到,因为它还没有Detach;
void onDetach(); //fragment与activity解除关联,fragment的所有的资源都被回收。
//与onAttach相对应,当Fragment与Activity的关联被取消时调用。
下面贴一下 activity和fragment同时运行时候的 生命周期?
开始启动:
05-07 05:55:08.553: I/Log(1990): oncreate
05-07 05:55:08.553: I/Log(1990): onAttach_Fragment
05-07 05:55:08.553: I/Log(1990): onCreate_Fragment
05-07 05:55:08.553: I/Log(1990): onCreateView_Fragment
05-07 05:55:08.553: I/Log(1990): onActivityCreated_Fragment
05-07 05:55:08.553: I/Log(1990): onStart
05-07 05:55:08.553: I/Log(1990): onStart_Fragment
05-07 05:55:08.553: I/Log(1990): onResume
05-07 05:55:08.553: I/Log(1990): onResume_Fragment
按下home按键
05-07 05:55:28.725: I/Log(1990): onPause_Fragment
05-07 05:55:28.725: I/Log(1990): onPause
05-07 05:55:29.221: I/Log(1990): onStop_Fragment
05-07 05:55:29.221: I/Log(1990): onStop
再回到界面
05-07 05:55:49.441: I/Log(1990): onRestart
05-07 05:55:49.441: I/Log(1990): onStart
05-07 05:55:49.441: I/Log(1990): onStart_Fragment
05-07 05:55:49.441: I/Log(1990): onResume
05-07 05:55:49.441: I/Log(1990): onResume_Fragment
销毁activity
05-07 05:59:02.293: I/Log(1990): onPause_Fragment
05-07 05:59:02.293: I/Log(1990): onPause
05-07 05:59:02.757: I/Log(1990): onStop_Fragment
05-07 05:59:02.757: I/Log(1990): onStop
05-07 05:59:02.757: I/Log(1990): onDestroyView_Fragment
05-07 05:59:02.757: I/Log(1990): onDestroy_Fragment
05-07 05:59:02.757: I/Log(1990): onDetach_Fragment
05-07 05:59:02.757: I/Log(1990): onDestroy
可以看出:当显示fragment的时候都先执行activity方法,当销毁的时候都是先执行fragment的方法,这样更好理解fragment是嵌套在activity中。
三、Fragment生命周期函数的场景演示
切换到该Fragment
11-29 14:26:35.095: D/AppListFragment(7649): onAttach
11-29 14:26:35.095: D/AppListFragment(7649): onCreate
11-29 14:26:35.095: D/AppListFragment(7649): onCreateView
11-29 14:26:35.100: D/AppListFragment(7649): onActivityCreated
11-29 14:26:35.120: D/AppListFragment(7649): onStart
11-29 14:26:35.120: D/AppListFragment(7649): onResume
屏幕灭掉:
11-29 14:27:35.185: D/AppListFragment(7649): onPause
11-29 14:27:35.205: D/AppListFragment(7649): onSaveInstanceState
11-29 14:27:35.205: D/AppListFragment(7649): onStop
屏幕解锁
11-29 14:33:13.240: D/AppListFragment(7649): onStart
11-29 14:33:13.275: D/AppListFragment(7649): onResume
切换到其他Fragment:
11-29 14:33:33.655: D/AppListFragment(7649): onPause
11-29 14:33:33.655: D/AppListFragment(7649): onStop
11-29 14:33:33.660: D/AppListFragment(7649): onDestroyView
切换回本身的Fragment:
11-29 14:33:55.820: D/AppListFragment(7649): onCreateView
11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated
11-29 14:33:55.825: D/AppListFragment(7649): onStart
11-29 14:33:55.825: D/AppListFragment(7649): onResume
回到桌面
11-29 14:34:26.590: D/AppListFragment(7649): onPause
11-29 14:34:26.880: D/AppListFragment(7649): onSaveInstanceState
11-29 14:34:26.880: D/AppListFragment(7649): onStop
回到应用
11-29 14:36:51.940: D/AppListFragment(7649): onStart
11-29 14:36:51.940: D/AppListFragment(7649): onResume
退出应用
11-29 14:37:03.020: D/AppListFragment(7649): onPause
11-29 14:37:03.155: D/AppListFragment(7649): onStop
11-29 14:37:03.155: D/AppListFragment(7649): onDestroyView
11-29 14:37:03.165: D/AppListFragment(7649): onDestroy
11-29 14:37:03.165: D/AppListFragment(7649): onDetach