Fragment生命周期详解及使用

        最近几年Android的迅速发展,SDK的不断完善,在SDK Android 3.0引入了一个新的核心类-Fragment(碎片)。除了提供大量重用外,它的可用性也很强。Fragment仅可存在于Activity的上下文内,没有Activity就无法使用Fragment。Fragment出现并使用的好处,在这就不多讲述了。下面从最基本的开始了解Fragment的生命周期开始:

一、生命周期

场景演示 : 切换到该Fragment

onAttach-onCreate-onCreateView-onActivityCreated-onStart-onResume

屏幕灭掉:

onPause-onSaveInstanceState-onStop

屏幕解锁

onStart-onResume

切换到其他Fragment:

onPause-onStop-onDestroyView

切换回本身的Fragment:

onCreateView-onActivityCreated-onStart-onResume

回到桌面

onPause-onSaveInstanceState-onStop

回到应用

onStart-onResume

退出应用

onPause-onStop-onDestroyView-onDestroy-onDetach

 

二、结构

Fragment就像是一个子Activity,但是Activity继承的是Context,而Fragment继承的是Object,Fragment不是Activity的扩展。

类似于Activity,Fragment可由系统自动保存并在以后还原,当系统还原的时候,将会调用无参的默认构造方法。所以,请确保Fragment存在默认的构造方法。

同Activty一样,Fragmet可在重新创建时将状态保存到一个Bundle对象,这个Bundle对象会被回送到该Fragment的onCreate()回调。同时,也会传递到onInflate()、onCreateView()和onActivityCreated()中。需要注意的是,这不是用于初始化Fragment的Bundle对象,你更应该可能在这个Bundle对象存储Frament的当前状态。

三、生命周期详解

创建Fragment对象,一个不错的方法是使用静态工厂方法实例化碎片:

publicstatic TestFragment newInstance(intindex) {
    TestFragment fragment = newTestFragment();
    Bundle args = newBundle();
    args.putInt("index", index);
    fragment.setArguments(args);
    returnfragment;
}
1、onInflate()

如果Fragment是布局内d<fragmet>标记定义(通常是在Activity的setContentView()来设置在的主要布局时),Frament将回调onInflate()。

@Override
publicvoid onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) {
    super.onInflate(activity, attrs, savedInstanceState);
}

如果是重新创建Fragment,并且之前在onSaveInstanceState()保存了状态,那么Bundle对象会包含保存的状态值。在onInflate()时预料你会读取特性值并保存它们供以后使用。

在这个阶段,实际对用户界面执行任何操作偶为时尚早,Fragment甚至都没有和Activity关联。

2、onAttach()
@Override
publicvoid onAttach(Activity activity) {
    super.onAttach(activity);
}

在与Activity关联后被回调,这里可以使用Activity的引用,但是在Fragment中有个getActivity()方法,它总是返回Fragment所附加的Activity。

另外,在Frament的整个生命周期中,可以调用getArguments()获得初始化参数Bundle,但是一旦Fragment附加到Activity后,就无法再次调用setArguments()。所以除了在最开始时,无法向初始化的Bundle添加内容。

 3、onCreate()
@Override
publicvoid onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

这个方法和Activity的类似,但是还不能把需要依赖于Activty布局的存在性的代码放在这里,因为我们还未获得Activity的onCreate()已完成的通知。

这个方法会传入以保存的Bundle对象(如果有),它会尽可能早地创建一个后台线程来获取此Fragment将需要的数据。

4、onCreateView()
@Override
publicView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    returnsuper.onCreateView(inflater, container, savedInstanceState);
}

在这里期望返回此Frament的一个布局。这个方法的一个参数是LayoutInflater,用于载入布局,还有一个ViewGroup类型的container的父元素,以及一个Bundle对象(如果有)。需要注意的是,这里不应该将布局附加到父元素的container中,该关联会在以后自动完成。

例如:

if(container == null) {
    returnnull;
}
View v = inflater.inflate(R.layout.pop_main, container, false);
TextView text = (TextView) v.findViewById(R.id.text);
text.setText("Text");
returnv;

如果container为null,这说明Fragment不可见,因为它没有附加任何的视图层次,这时候可以返回null,但一般不用处理。

5、onActivityCreated()
@Override
publicvoid onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

该方法会在Activity完成其onCreate()后调用。现在,Activty的布局已经准备好并可用。这是在用户看到界面之前,你可以对用户界面执行最后调整的地方。

 
6、onStart()和onResume()

这2个方法都是和Activity对应的方法相绑定的。 

7、onPause()

Fragment的第一个撤销回调,与Activity对应的方法相绑定。

8、onSaveInstanceState()

和Actiity一样,Fragment也可以保存状态,虽然这个方法通常是在onPause()后调用,但当Fragment需要保存时,其所属的Activty可以直接调用这个回调方法,这随时都可以在发生在onDestroy()之前。

其他的还有onStop()、onDestroyView()、onDestroy()等。destroy后,fragment不再可用,但是它依然附加在activity上,只是不能执行其它操作。

最后一个是onDetach()回调,fragment就不会再与其activity绑定,fragment不再拥有视图层次结构,它的所有资源也应该已释放。

 

四、setRetainInstance()

可以指定不希望在重新创建activity时完全销毁fragment,以便fragment可以恢复。

调用setRetainInstance()的最佳时机是在onCreate()???

如果为true,则fragment对象会被保存在内存中:

在销毁时,直接从onDestroyView()到onDeatch(),跳过了onDestroy();

在创建的时候,直接从onAttach()到onCreateView(),跳过了onCreate()。

 

五、隐藏和显示

在Activity中,我们常常使用onPause()和onResume()来判当前活动是否失去、获得焦点,但是在Fragment中有一些微妙的变化。由于Fragment是依附在其所属的Activity的,虽然它也有onResume()和onPause()方法,但我发现这2个方法的调用机制,并非和Activity是同步的。也就是说,Activity触发了onPause(),对应的Fragment却没有回调onPause()。

举个例子,在MainActivity中,管理了3个Fragment,用户需要切换不同的页面。由于我采用的是hide和show,那么我就可以根据如下方法来判断Fragment的状态。

@Override
   publicvoid onHiddenChanged(booleanhidden) {
       super.onHiddenChanged(hidden);
 
      // 切换侧边页面的时候触发
       if(hidden) {
           // ...
       }
   }

六、Fragment之间的通信方式

除了startActivity、startActivtyForResult,还有如下通信机制:

当一个fragment希望启动另一个fragment时,有一项功能支持调用fragment使用被调用fragment来设置它的身份。

例如在CurrentFragment中,有如下代码:

TestFragment tf = newTestFragment();
tf.setTargetFragment(this,0);
getFragmentManager().beginTransaction().add(tf,"tag").commit();

被调用碎片-TestFragment对象tf,将目标碎片设置为当前碎片,并且使用碎片事务将被调用碎片tf添加到了碎片管理器和Activity中。

当被调用碎片tf运行时,tf可以通过getTargetFragment()方法返回调用碎片的引用。有了这个引用,tf可以调用CurrentFragment的方法,甚至直接访问视图组件。

例如CurrentFragment布局有text1,那么tf可以:

TextView tv = getTargetFragment().getView().findViewById(R.id.text1);
tv.setText("Set from the called fragment!");

以上就是Fragment的生命周期详解,以及在开发的时候使用到Fragment的生命周期来开发之处,Fragment的其它运用开发在之后的博客中将会继续记录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值