Fragment管理最佳实践

现在的app视图中tab+fragment是最常用的一种布局,但是如果使用才是更简洁更有效的呢?下面通过一个demo的分类测试来分析下:

add remove replace detach attach hide show这些方法的使用对Fragment生命周期的影响分析:

顺便分析下Fragment所依赖的Activity的生命周期;

测试代码如下:

MainActivity的代码如下:

package com.testfragmentlifecircle;

import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends FragmentActivity {
    private static final String TAG = "test-MainActivity";

    // 首页
    private IndexFragment indexFragment;
    // 我的页面
    private MineFragment mineFragment;
    // 更多页面
    private MoreFragment moreFragment;
    private TextView[] textviews;
    private Fragment[] fragments;
    public int index;
    // 当前fragment的index
    private int currentTabIndex;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "--onCreate");
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        textviews = new TextView[3];
        textviews[0] = (TextView) findViewById(R.id.index_text);
        textviews[1] = (TextView) findViewById(R.id.mine_text);
        textviews[2] = (TextView) findViewById(R.id.more_text);
        textviews[0].setSelected(true);
        indexFragment = new IndexFragment();
        mineFragment = new MineFragment();
        moreFragment = new MoreFragment();
        fragments = new Fragment[]{indexFragment, mineFragment, moreFragment};
        // 添加显示第一个fragment
        /*用add、hide和show测试的初始化的代码*/
//        getSupportFragmentManager().beginTransaction()
//                .add(R.id.fragment_container, indexFragment)
//                .add(R.id.fragment_container, mineFragment)
//                .add(R.id.fragment_container, moreFragment)
//                .show(indexFragment).hide(mineFragment).hide(moreFragment)
//                .commit();
        /*用replace测试的初始化的代码*/
//        getSupportFragmentManager().beginTransaction()
//                .replace(R.id.fragment_container, indexFragment)
//                .addToBackStack(null)
//                .commit();
        /*用attach和dettach测试的初始化的代码*/
        getSupportFragmentManager().beginTransaction()
                .add(R.id.fragment_container, indexFragment)
                .add(R.id.fragment_container, mineFragment)
                .add(R.id.fragment_container, moreFragment)
                .attach(indexFragment)
                .detach(mineFragment)
                .detach(moreFragment)
                .commit();
    }

    private void refreshTab() {
        if (currentTabIndex != index) {
            FragmentTransaction trx = getSupportFragmentManager()
                    .beginTransaction();
            /*用add、hide和show测试的切换Fragment的代码*/
//            for (int i = 0; i < fragments.length; i++) {
//                if (!fragments[i].isAdded()) {
//                    trx.add(R.id.fragment_container, fragments[i]);
//                }
//                if (i != index) {
//                    trx.hide(fragments[i]);
//                } else {
//                    trx.show(fragments[i]);
//                }
//            }
            /*用replace测试的切换Fragment的代码*/
//            trx.addToBackStack(null);
//            trx.replace(R.id.fragment_container, fragments[index]);
            /*用attach和dettach测试的切换Fragment的代码*/
            for (int i = 0; i < fragments.length; i++) {
                if (!fragments[i].isAdded()) {
                    trx.add(R.id.fragment_container, fragments[i]);
                }
                if (i != index) {
                    trx.detach(fragments[i]);
                } else {
                    trx.attach(fragments[i]);
                }
            }
            trx.commit();

            textviews[currentTabIndex].setSelected(false);
            textviews[index].setSelected(true);
            currentTabIndex = index;
        }
    }

    public void onTabClicked(View view) {
        switch (view.getId()) {
            case R.id.index:
                if (0 != index) {
                    index = 0;
                }
                break;
            case R.id.mine:
                if (1 != index) {
                    index = 1;
                }
                break;
            case R.id.more:
                if (2 != index) {
                    index = 2;
                }
                break;
        }
        refreshTab();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        Log.e(TAG, "--onBackPressed");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e(TAG, "--onDestroy");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "--onPause");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.e(TAG, "--onResume");
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.e(TAG, "--onNewIntent");
    }

    @Override
    protected void onPostResume() {
        super.onPostResume();
        Log.e(TAG, "--onPostResume");
    }

    @Override
    protected void onResumeFragments() {
        super.onResumeFragments();
        Log.e(TAG, "--onResumeFragments");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.e(TAG, "--onSaveInstanceState");
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.e(TAG, "--onStart");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.e(TAG, "--onStop");
    }

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        Log.e(TAG, "--onAttachFragment");
    }

}

BaseFragment代码如下:

package com.testfragmentlifecircle;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

/**
 * 作 者: yc
 * 创 建:2016/4/27-11:52
 * 版 本:
 */
public class BaseFragment extends Fragment {

    protected final String TAG = "test-" + this.getClass().getSimpleName();

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Log.e(TAG,"--onAttach");
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG,"--onCreate");
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.e(TAG,"--onCreateView");
        TextView textView = new TextView(getContext());
        textView.setText(TAG);
        return textView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e(TAG,"--onActivityCreated");
    }

    @Override
    public void onStart() {
        super.onStart();
        Log.e(TAG,"--onStart");
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e(TAG,"--onResume");
    }

    @Override
    public void onPause() {
        super.onPause();
        Log.e(TAG,"--onPause");
    }

    @Override
    public void onStop() {
        super.onStop();
        Log.e(TAG,"--onStop");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Log.e(TAG,"--onDestroyView");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e(TAG,"--onDestroy");
    }

    @Override
    public void onDetach() {
        super.onDetach();
        Log.e(TAG,"--onDetach");
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        Log.e(TAG,"--onHiddenChanged--hidden="+hidden);
        super.onHiddenChanged(hidden);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Log.e(TAG,"--onSaveInstanceState");
    }
}

三个Fragment分别为IndexFragment、MineFragment和MoreFragment,代码分别如下:

package com.testfragmentlifecircle;

/**
 * 作 者: yc
 * 创 建:2016/4/27-12:36
 * 版 本:
 */
public class IndexFragment extends BaseFragment {

}
package com.testfragmentlifecircle;

/**
 * 作 者: yc
 * 创 建:2016/4/27-12:36
 * 版 本:
 */
public class MineFragment extends BaseFragment {

}
package com.testfragmentlifecircle;

/**
 * 作 者: yc
 * 创 建:2016/4/27-12:36
 * 版 本:
 */
public class MoreFragment extends BaseFragment {

}

MainActivity布局activity_main.xml代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/other_bg"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/main_bottom"
        android:layout_width="match_parent"
        android:layout_height="48dip"
        android:layout_alignParentBottom="true"
        android:background="@color/index_tab_color"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <RelativeLayout
            android:id="@+id/index"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onTabClicked"
            android:paddingBottom="2dip"
            android:paddingTop="5dip">

            <TextView
                android:id="@+id/index_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="2dp"
                android:text="@string/index"
                android:textColor="@color/clicked_text_color"
                android:textSize="10sp" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/mine"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onTabClicked"
            android:paddingBottom="2dip"
            android:paddingTop="5dip">

            <TextView
                android:id="@+id/mine_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="2dp"
                android:text="@string/mine"
                android:textColor="@color/clicked_text_color"
                android:textSize="10sp" />
        </RelativeLayout>

        <RelativeLayout
            android:id="@+id/more"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:onClick="onTabClicked"
            android:paddingBottom="2dip"
            android:paddingTop="5dip">

            <TextView
                android:id="@+id/more_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="2dp"
                android:text="@string/more"
                android:textColor="@color/clicked_text_color"
                android:textSize="10sp" />
        </RelativeLayout>
    </LinearLayout>

    <View
        android:id="@+id/view_temp"
        android:layout_width="match_parent"
        android:layout_height="0.1dp"
        android:layout_above="@id/main_bottom"
        android:background="@color/index_divider_color" />

    <RelativeLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@id/view_temp" />

</RelativeLayout>

分类测试及日志分析:

1.通过add添加,通过hide和show控制Fragment的隐藏和显示的切换

1.1——————————————-初始化,初始显示IndexFragment,隐藏MineFragment和MoreFragment:

E/test-MainActivity: –onCreate

/com.testfragmentlifecircle E/test-MineFragment: –onHiddenChanged–hidden=true

/com.testfragmentlifecircle E/test-MoreFragment: –onHiddenChanged–hidden=true

/com.testfragmentlifecircle E/test-IndexFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-IndexFragment: –onCreate

/com.testfragmentlifecircle E/test-IndexFragment: –onCreateView

/com.testfragmentlifecircle E/test-IndexFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-MineFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-MineFragment: –onCreate

/com.testfragmentlifecircle E/test-MineFragment: –onCreateView

/com.testfragmentlifecircle E/test-MineFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-MoreFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-MoreFragment: –onCreate

/com.testfragmentlifecircle E/test-MoreFragment: –onCreateView

/com.testfragmentlifecircle E/test-MoreFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

/com.testfragmentlifecircle E/test-MineFragment: –onStart

/com.testfragmentlifecircle E/test-MoreFragment: –onStart

E/test-MainActivity: –onStart

E/test-MainActivity: –onResume

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

/com.testfragmentlifecircle E/test-MineFragment: –onResume

/com.testfragmentlifecircle E/test-MoreFragment: –onResume

E/test-MainActivity: –onResumeFragments

E/test-MainActivity: –onPostResume

结论:初始化隐藏的Fragment会回调onHiddenChanged,初始化显示的不会回调onHiddenChanged,因为add进去的Fragment的默认就是显示的,

所以add之后再调用hide的时候从显示变成了隐藏才会回调onHiddenChanged方法。

结论:onAttachFragment会在每个Fragment关联(onAttach)之后回调,onResumeFragments会在所有Fragment初始化完成之后回调一次

1.2——————————————-退出应用,即退出MainActivity:

E/test-MainActivity: –onBackPressed

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

/com.testfragmentlifecircle E/test-MineFragment: –onPause

/com.testfragmentlifecircle E/test-MoreFragment: –onPause

E/test-MainActivity: –onPause

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

/com.testfragmentlifecircle E/test-MineFragment: –onStop

/com.testfragmentlifecircle E/test-MoreFragment: –onStop

E/test-MainActivity: –onStop

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroyView

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroy

/com.testfragmentlifecircle E/test-IndexFragment: –onDetach

/com.testfragmentlifecircle E/test-MineFragment: –onDestroyView

/com.testfragmentlifecircle E/test-MineFragment: –onDestroy

/com.testfragmentlifecircle E/test-MineFragment: –onDetach

/com.testfragmentlifecircle E/test-MoreFragment: –onDestroyView

/com.testfragmentlifecircle E/test-MoreFragment: –onDestroy

/com.testfragmentlifecircle E/test-MoreFragment: –onDetach

E/test-MainActivity: –onDestroy

结论:走完退出流程

结论:

1.3——————————————-从IndexFragment切换到MineFragment:

/com.testfragmentlifecircle E/test-IndexFragment: –onHiddenChanged–hidden=true

/com.testfragmentlifecircle E/test-MineFragment: –onHiddenChanged–hidden=false

结论:Fragment页面之间通过hide和show进行切换,并不会回调Fragment的任何生命周期方法,只会回调onHiddenChanged

结论:

1.4——————————————-从前台切换到后台:

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

/com.testfragmentlifecircle E/test-MineFragment: –onPause

/com.testfragmentlifecircle E/test-MoreFragment: –onPause

E/test-MainActivity: –onPause

E/test-MainActivity: –onSaveInstanceState

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

/com.testfragmentlifecircle E/test-MineFragment: –onStop

/com.testfragmentlifecircle E/test-MoreFragment: –onStop

E/test-MainActivity: –onStop

结论:当所依赖的MainActivity切换到后台,Fragment同样会执行对应的生命周期方法:onPause–onStop

结论:这里说明一点,这里没有打印这些Fragment的onSaveInstanceState方法的回调,其实这个和MainActivity的执行是一致的

1.5——————————————-从后台切换到前台:

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

/com.testfragmentlifecircle E/test-MineFragment: –onStart

/com.testfragmentlifecircle E/test-MoreFragment: –onStart

E/test-MainActivity: –onStart

E/test-MainActivity: –onResume

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

/com.testfragmentlifecircle E/test-MineFragment: –onResume

/com.testfragmentlifecircle E/test-MoreFragment: –onResume

E/test-MainActivity: –onResumeFragments

E/test-MainActivity: –onPostResume

结论:当所依赖的MainActivity切换到前台,Fragment同样会执行对应的生命周期方法:onStart–onResume

结论:

1.6 大总结:在初始化和前后台切换的过程中Fragment和MainActivity对应生命周期的回调是一致的,

特殊点在于Fragment之间来回切换并不会回调Fragment和MainActivity的任何生命周期方法,但是会

回调onHiddenChanged方法,并且初始化过程中只有add之后再调用hide的时候从显示变成了隐藏才会

回调onHiddenChanged方法,这样如果我们想要在摸个Fragment显示的时候做一些和onResume方法中同

样的初始化工作就不会发生重复和冲突,所以我们可以在Fragment显示的时候在onHiddenChanged的

hidden=false的时候做onResume中同样的初始化工作。(由此可见Google大佬们的设计之精妙)

用这种方法就能实现Fragment切换的最佳实践:切换显示装填的时候并不会销毁或者重新创建,而是

每个Fragment都始终加载完成并保存在内存中,并且在任何时候进行显示状态的切换都有回调可以做

初始化或者收尾工作:1.Fragment之间切换可以在onHiddenChanged中做工作 2.其它情况下都有对应

的生命周期方法可供回调

2.通过replace方法控制Fragment的隐藏和显示的切换

2.1——————————————-初始化,初始显示IndexFragment:

E/test-MainActivity: –onCreate

/com.testfragmentlifecircle E/test-IndexFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-IndexFragment: –onCreate

/com.testfragmentlifecircle E/test-IndexFragment: –onCreateView

/com.testfragmentlifecircle E/test-IndexFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

E/test-MainActivity: –onStart

E/test-MainActivity: –onResume

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

E/test-MainActivity: –onResumeFragments

E/test-MainActivity: –onPostResume

结论:

结论:

2.2——————————————-从IndexFragment切换到MineFragment:(直接replace)

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroyView

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroy

/com.testfragmentlifecircle E/test-IndexFragment: –onDetach

/com.testfragmentlifecircle E/test-MineFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-MineFragment: –onCreate

/com.testfragmentlifecircle E/test-MineFragment: –onCreateView

/com.testfragmentlifecircle E/test-MineFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-MineFragment: –onStart

/com.testfragmentlifecircle E/test-MineFragment: –onResume

———————————————-再切换回IndexFragment

/com.testfragmentlifecircle E/test-MineFragment: –onPause

/com.testfragmentlifecircle E/test-MineFragment: –onStop

/com.testfragmentlifecircle E/test-MineFragment: –onDestroyView

/com.testfragmentlifecircle E/test-MineFragment: –onDestroy

/com.testfragmentlifecircle E/test-MineFragment: –onDetach

/com.testfragmentlifecircle E/test-IndexFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-IndexFragment: –onCreate

/com.testfragmentlifecircle E/test-IndexFragment: –onCreateView

/com.testfragmentlifecircle E/test-IndexFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

结论:replace内部实现,就是remove掉之前所添加(add)过的所有Fragment,然后再添加并显示当前Fragment,

所以之前的Fragment会被彻底删除掉。

结论:

2.3——————————————-从IndexFragment切换到MineFragment:(给FragmentTransaction设置addToBackStack(null)之后再replace)

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroyView

/com.testfragmentlifecircle E/test-MineFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-MineFragment: –onCreate

/com.testfragmentlifecircle E/test-MineFragment: –onCreateView

/com.testfragmentlifecircle E/test-MineFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-MineFragment: –onStart

/com.testfragmentlifecircle E/test-MineFragment: –onResume

———————————————-再切换回IndexFragment

/com.testfragmentlifecircle E/test-MineFragment: –onPause

/com.testfragmentlifecircle E/test-MineFragment: –onStop

/com.testfragmentlifecircle E/test-MineFragment: –onDestroyView

/com.testfragmentlifecircle E/test-IndexFragment: –onCreateView

/com.testfragmentlifecircle E/test-IndexFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

结论:这种实现方式即没有彻底销毁Fragment对象,还能在Fragment切换的时候正常回调onResume方法,比较接近最佳实践,

但是只是没有彻底销毁Fragment对象,而是把对象存储到内存中,但是Fragment中的试图仍需要重新构建。

我们通常复写Fragment就是从onCreateView方法开始,等于说对我们而言这些页面初始化工作每次显示都需要重来,只是framework层

不需要彻底销毁Fragment对象而已,所以这种方式可以解决生命周期一致性问题,但是并不能很好的解决Fragment之间相互切换的时候

的重新加载问题,并不是完美的最佳实践。

结论:

3.通过dettach和attach方法控制Fragment的隐藏和显示的切换

3.1——————————————-初始化,初始显示IndexFragment:

E/test-MainActivity: –onCreate

/com.testfragmentlifecircle E/test-IndexFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-IndexFragment: –onCreate

/com.testfragmentlifecircle E/test-MineFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-MineFragment: –onCreate

/com.testfragmentlifecircle E/test-MoreFragment: –onAttach

E/test-MainActivity: –onAttachFragment

/com.testfragmentlifecircle E/test-MoreFragment: –onCreate

/com.testfragmentlifecircle E/test-IndexFragment: –onCreateView

/com.testfragmentlifecircle E/test-IndexFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

E/test-MainActivity: –onStart

E/test-MainActivity: –onResume

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

E/test-MainActivity: –onResumeFragments

E/test-MainActivity: –onPostResume

结论:只有初始化和MainActivity想关联(attach)的Fragment才会走完显示的生命周期,而初始化和MainActivity

不关联(dettach)的Fragment只回调onAttach和onCreate就完了,这说明不关联的Fragment已经创建好并且存储在

内存中

结论:

3.2——————————————-退出应用,即退出MainActivity:

E/test-MainActivity: –onBackPressed

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

E/test-MainActivity: –onPause

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

E/test-MainActivity: –onStop

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroyView

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroy

/com.testfragmentlifecircle E/test-IndexFragment: –onDetach

/com.testfragmentlifecircle E/test-MineFragment: –onDestroy

/com.testfragmentlifecircle E/test-MineFragment: –onDetach

/com.testfragmentlifecircle E/test-MoreFragment: –onDestroy

/com.testfragmentlifecircle E/test-MoreFragment: –onDetach

E/test-MainActivity: –onDestroy

结论:

结论:

3.3——————————————-从IndexFragment切换到MineFragment:

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

/com.testfragmentlifecircle E/test-IndexFragment: –onDestroyView

/com.testfragmentlifecircle E/test-MineFragment: –onCreateView

/com.testfragmentlifecircle E/test-MineFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-MineFragment: –onStart

/com.testfragmentlifecircle E/test-MineFragment: –onResume

———————————————-再切换回IndexFragment

/com.testfragmentlifecircle E/test-IndexFragment: –onCreateView

/com.testfragmentlifecircle E/test-IndexFragment: –onActivityCreated

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

/com.testfragmentlifecircle E/test-MineFragment: –onPause

/com.testfragmentlifecircle E/test-MineFragment: –onStop

/com.testfragmentlifecircle E/test-MineFragment: –onDestroyView

结论:由此可见attach和dettach的使用,和replace+addToBackStack(null)的使用效果是一样的:

当前没有显示的Fragment的对象并没有被彻底销毁,而是存储在回收栈中,当需要显示的时候只需要重新构建布局,

从onDestroyView开始就行了。所以对于即不要每次都重新加载有想要生命周期一致的情况,这同样不是完美的最佳实践。

结论:

3.4——————————————-从前台切换到后台:

/com.testfragmentlifecircle E/test-IndexFragment: –onPause

E/test-MainActivity: –onPause

/com.testfragmentlifecircle E/test-IndexFragment: –onSaveInstanceState

/com.testfragmentlifecircle E/test-MineFragment: –onSaveInstanceState

/com.testfragmentlifecircle E/test-MoreFragment: –onSaveInstanceState

E/test-MainActivity: –onSaveInstanceState

/com.testfragmentlifecircle E/test-IndexFragment: –onStop

E/test-MainActivity: –onStop

———————————————-再切换回前台

/com.testfragmentlifecircle E/test-IndexFragment: –onStart

E/test-MainActivity: –onStart

E/test-MainActivity: –onResume

/com.testfragmentlifecircle E/test-IndexFragment: –onResume

E/test-MainActivity: –onResumeFragments

E/test-MainActivity: –onPostResume

结论:只有当前处于关联状态的Fragment会执行和MainActivity一致的生命周期

结论:

4.总结:Fragment管理的最佳实践:add、hide和show,并通过onHiddenChanged完成Fragment之间切换时候的初始化工作。

实践目标:

1.每个Fragment显示状态切换的时候既不会销毁和重建对象,也不会销毁和重建布局

2.通过onHiddenChanged完成Fragment之间切换完成前后台切换时候onResume里面需要做的初始化工作,弥补了生命周期不

一致所带来的Fragment之间切换时候的初始化工作不能完全同步的问题

API不再逐个分析,参考:

http://www.pocketdigi.com/20141006/1385.html

http://blog.csdn.net/buaaroid/article/details/48265105

时间: 2024-10-08 01:41:12

Fragment管理最佳实践的相关文章

Android学习路线(二十四)ActionBar Fragment运用最佳实践

通过前面的几篇博客,大家看到了Google是如何解释action bar和fragment以及推荐的用法.俗话说没有demo的博客不是好博客,下面我会介绍一下action bar和fragment在实战中的应用,以及相关demo源码,希望和大家相互交流. 了解过fragment的同学们应该都知道,fragment是android 3.0版本才出现的的,因此如果要在支持android 3.0一下版本的工程中使用fragment的话是需要添加Support Library的.具体如何添加我就不再赘述

Android 6.0 运行时权限管理最佳实践

Android 6.0 运行时权限管理最佳实践 版权声明:转载必须注明本文转自严振杰的博客: http://blog.yanzhenjie.com 这是一篇迟来的博客,Android M已经发布一年多了(6.0的变化),在Android M中权限系统被重新设计,发生了颠覆性的变化,很多人把握不好这个变化,一是对这个权限策略和套路还没有摸透,二是没有一个很好的实践来支撑,在我的技术开发群里很多人问我关于权限的问题,往往我都没有直接回答,因为这个问题不是一两句说的清楚的,这几点是今天我写这篇博客的原

《国际项目集管理最佳实践与实战应用》大型复杂项目与项目群管理工作坊

<国际项目集管理最佳实践与实战应用>大型复杂项目与项目群管理工作坊 Program Management Training 主办单位:共创国际-项目管理者联盟 2015年4月10.11.12日 北京 & 课程前言 项目集(PROGRAM)定义为“经过协调管理以获取单独管理它们时无法取得收益与控制的一组关联的项目和项目集活动.”从组织战略的角度来看,项目集管理主要是指组织为实现其战略目标或为其客户提供整体解决方案而在组织高层针对战略性资源进行跨界整合的管理活动. 在全球经济一体化的背景下

事务管理最佳实践全面解析

事务管理 事务是一个单元的工作,要么全做,要么全不做. 事务管理对于维持数据库系统内部保存的数据逻辑上的一致性.完整性,起着至关重要的作用. 如:一个银行应用软件中,转帐的操作中,需要先在A用户帐户中减去资金,然后再在B用户帐户中增加相应的资金.如果完成A帐户操作后,由于系统故障或者网络故障,没有能够完成接下来的操作,那么A帐户中的资金就白白流失了.显然,客户是无法接受这样的结果的! 如果我们把一个A和B帐户的操作放在一个事务单元中,那么如果遇到上述异常情况,A帐户减少资金的操作会回滚.A帐户的

ActionBar Fragment运用最佳实践

ActionBar Fragment运用最佳实践

《项目集管理标准》:全球项目集管理最佳实践

<项目集管理标准>是全球项目集管理最佳实践           <项目集管理标准>(The Standard for Program Management)是由美国项目管理协会推出的一个重要的国家性的,也是事实上的全球性标准.标准详细描述了项目集管理的内容,促进不同项目小组之间进行有效沟通和资源调配.提供了帮助人们理解如何通过提升相互关联的组件的交付能力从而促进组织战略实现的重要且基本的内容.在大多数情况对大部分项目集而言,被认为是清晰.完整的.相关的和公认的在项目集管理中良好实践

密码管理最佳实践

为每个在线网站和服务设置不同的密码,对于保证你使用网络时的安全来说是至关重要的.下面由Personal Technology的专栏作家Geoffrey Fowler,向你展示密码管理程序是如何帮助你记录所有这些登录信息的. 我有超过150个不同的登录项和账户.要记住这么多的密码,我必须成为“雨人”才行.于是我开始搜寻能够储存我所有的密码的最好的服务,最终将名单削减为了四个,它们兼顾了可用性和安全性:1Password.Dachlane.LastPass和PasswordBox. LastPass

Azure虚拟机管理最佳实践之用户凭据

还记的之前老猫关于通过Powershell远程管理Azure中虚拟机的博文的脚本中,每个虚拟机访问都需要通过get-credential交互方式取得用于访问的用户凭据,但是这这种方式每次都要进行用户交互,如果反复运行的脚本显然不是个好方式,如何加密保留用户的凭据以便反复使用就是个最佳实践的内容.当然现在国际版Azure中提供的自动化服务功能包含的Asset可以安全保留凭据用于自动化脚本调用,由于目前国内的Azure服务还没有这项功能,因此暂时只能按下不表了,当然如果只能这样本文也就结束了,这里介

Mesos+Zookeeper+Marathon+Docker分布式集群管理最佳实践

参考赵班长的unixhot以及马亮blog 笔者QQ:572891887 Linux架构交流群:471443208 1.1Mesos简介 Mesos是Apache下的开源分布式资源管理框架,它被称为分布式系统的内核.Mesos最初是由加州大学伯克利分校的AMPLab开发,后在Twitter得到广泛使用. Mesos-Master:主要负责管理各个framework和slave,并将slave上的资源分配给各个framework. Mesos-Slave:负责管理本节点上的各个mesos-task