手把手,嘴对嘴,Fragment使用

这里使用v4.app.Fragment ,因为他兼容更低版本 ,他需要你的Activity继承FragmentActivity而不是Activity ,除非你使用的是app.Fragmetn,app.Fragment兼容的最低版本为3.0。

Fragmetn生命周期

先看下Fragment的生命周期:

这是我盗的图

下面用代码说话:

public class FragmentA extends android.support.v4.app.Fragment{

    /**
     * 当Fragment与Activity发生关联时调用。
     *
     * @param context 当前Activity的Context
     */
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        L("onAttach");
    }

    /**
     * 在创建fragment时系统会调用此方法。
     * 在实现代码中,你可以初始化想要在fragment中保持的那些必要组件(这里的组件是指除了view之外的东西,比如需要进行界面展示的关键数据)
     * 当fragment处于暂停或者停止状态之后可重新启用它们。
     *
     * @param savedInstanceState 如果你在onSaveInstanceState()将一些值保存到了Bundle中,在这里你可以拿到他
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String aaa = "";
        if (savedInstanceState != null)
            aaa = savedInstanceState.getString("aaa");
        L("onCreate _ " + aaa);
    }

    /**
     * 在第一次为fragment绘制用户界面时系统会调用此方法
     * 为fragment绘制用户界面,这个函数必须要返回所绘出的fragment的根View
     * 如果fragment没有用户界面可以返回空。
     *
     * @param inflater 用来填充的Layout
     * @param container 父容器
     * @param savedInstanceState 如果你在onSaveInstanceState()将一些值保存到了Bundle中,在这里你可以拿到他
     * @return
     */
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        String aaa = "";
        if (savedInstanceState != null)
            aaa = savedInstanceState.getString("aaa");
        L("onCreateView _ " + aaa);
        return inflater.inflate(R.layout.fragment_a , container , false);
    }

    /**
     * 当Activity的onCreate方法返回时调用
     *
     * @param savedInstanceState 如果你在onSaveInstanceState()将一些值保存到了Bundle中,在这里你可以拿到他
     */
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        String aaa = "";
        if (savedInstanceState != null)
            aaa = savedInstanceState.getString("aaa");
        L("onActivityCreated _ " + aaa);
    }

    /**
     *  将当前Fragment切到后台再切回来的时候,如果这期间时间不长,他将会被第一个调用
     */
    @Override
    public void onStart() {
        super.onStart();
        L("onStart");
    }

    /**
     * 将当前Fragment切到后台再切回来的时候,如果这期间时间不长,他将会被第二个调用
     */
    @Override
    public void onResume() {
        super.onResume();
        L("onResume");
    }

    /**
     * 系统回调用该函数作为用户离开fragment的第一个预兆(尽管这并不总意味着fragment被销毁)
     * 在当前用户会话结束之前,通常要在这里提交任何应该持久化的变化(因为用户可能不再返回)。
     */
    @Override
    public void onPause() {
        super.onPause();
        L("onPause");
    }

    /**
     * 在onPause之后调用,在这里你可以将当前Fragment的状态保存下来,
     * 因为用户可能会在这个Fragment被回收之后才回来,为了确保他们回来后看到的界面依然是离开前的样子
     * 你需要保存一些数据信息到Bundle,并在onCreateView()中重新设置到界面上
     * @param outState
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("aaa", "FragmentA_Bundle");
        L("onSaveInstanceState");
    }

    /**
     * 半死不活
     */
    @Override
    public void onStop() {
        super.onStop();
        L("onStop");
    }

    /**
     * 这个还不太明白什么意思……
     */
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        L("onDestroyView");
    }

    /**
     * 这个Fragment已经死透了
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        L("onDestroy");
    }

    /**
     * 这个Fragment已经跟Activity断绝关系了
     */
    @Override
    public void onDetach() {
        super.onDetach();
        L("onDetach");
    }

    /**
     * 这是个LOG……
     * @param msg 你想说的话……
     */
    private void L(String msg){
        Log.i("FragmentTag" , "FragmentA : "  + msg);
    }

}

我将每一个生命周期的回调都打上了LOG。然后我是这么操作的:打开App,Fragment一张傻脸呈现在我面前,然后我赶紧按返回键退出App。LOG信息就是下面这样了。
onAttach
onCreate
onCreateView
onActivityCreated
onStart
onResume
onPause
onSaveInstanceState
onStop
onDestroyView
onDestroy
onDetach

具体每个回调的调用时机,都在注释中。这里要说的是, 如果你看到Fragment的傻脸时候按Home键,他会调用onPause ,onSaveInstanceState , onStop , 然后再回到他那张傻脸的时候会调用onStart , onResume。如果在这期间作了别的操作,比如说浏览了一些黄图,摇了几个妹子,然后再回来他大概已经被回收了,这时他会调用onCreate,onCreateView,onActivityCreated,onStart,onResume,我理解的是你可以在onCreateView()中通过Bundle将界面恢复到用户离开之前的样子。


Fragment切换

对Fragment的管理,中国人儿歪果仁儿都使用FragmentManager,通过他可以得到一个FragmentTransaction,字面意思就是事务,在对Fragment做了一系列操作后,提交事务你的操作就会或报错或改变或没反应的在屏幕上应验。

首先要了解一下FragmentTransaction的这4个方法:

add() 添加

replace() 替换

hide() 隐藏

show() 显示

英语6级不黑不吹~这里先这样,后面会告诉你他们怎么用。

这里主要说Fragment之间的切换,两种方式:
1 . 替换 replace()
2 . 切换 hide() add() show()
看需求而定,如果Fragment之间的切换并不是特别频繁,那么使用1.替换会更好一点。如果你是频繁切换,2.切换会性能更优。

这个MainActivity中,使用了“1.替换”的方式切换Fragment:

/**
 * 界面上有两个Button
 * 点击A切换到FragmentA
 * 点击B切换到FragmentB
 */
public class MainActivity extends FragmentActivity {

    Fragment fragmentA;
    Fragment fragmentB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentA = new FragmentA();
        fragmentB = new FragmentB();
    }

    /**
     * ButtonA的点击事件
     * @param view
     */
    public void A(View view){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.f , fragmentA).commit();
    }

    /**
     * ButtonB的点击事件
     * @param view
     */
    public void B(View view){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.replace(R.id.f , fragmentB).commit();
    }

}

打印Log,会发现切换期间两个Fragment是在不停初始化的,也就是说,我干死你我再站这,你再干死我你再站这,有你没我有我没你。


在这个MainActivity中,使用了“2.切换”的方式在两个Fragment之间跳转,缠绵,周旋,游走,并且
个人认为这样才是Fragment之间切换的正确姿势 ,当然,不同的体位是要根据不同喜好的人改变的,这里同理,根据需求而定:

/**
 * 界面上有两个Button
 * 点击A切换到FragmentA
 * 点击B切换到FragmentB
 */
public class MainActivity extends FragmentActivity {

    Fragment fragmentA;
    Fragment fragmentB;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        fragmentA = new FragmentA();
        fragmentB = new FragmentB();
    }

    /**
     * ButtonA的点击事件
     * @param view
     */
    public void A(View view){
        hideFragment();
        showWhat(fragmentA);
    }

    /**
     * ButtonB的点击事件
     * @param view
     */
    public void B(View view){
        hideFragment();
        showWhat(fragmentB);
    }

    private void hideFragment(){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
        if (fragmentList != null){
            for (int i = 0; i < fragmentList.size(); i++) {
                ft.hide(fragmentList.get(i));
            }
            ft.commit();
        }
    }

    private void showWhat(Fragment fragment){
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        if (!fragment.isAdded()){
            ft.add(R.id.f, fragment);
        }else{
            ft.show(fragment);
        }
        ft.commit();
    }

}

打印Log,会发现切换期间完全没有走任何一个生命周期,除了第一次add()的时候。这就相当于你去前台表演的时候我就去幕后了,我们轮流上台。说到轮流,我想起了一首诗。“南村群童欺我老无力,轮流与我发生性关系”,哈哈哈哈哈。算福利了,送给大家。


好了 基本使用就这些了,下面还会有一些别的花样儿等着你。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章