Fragment生命周期那些事

提笔犯怵,好久没总结干货了,知识普遍都是碎片化的,记录在云笔记里的比较多和杂。

最近项目用了BottomBar这个开源控件,狂拽炫酷吊炸天,视觉效果很好,还支持behavior,与NestedScrollView结合可以下拉隐藏,上滑显示,上个图。
这里写图片描述 这里写图片描述

以上都不是重点————分割———埋个雷–使用fragmentmanager管理Fragment的生命周期方法——
项目要使用fragment,fragment切换不需要滑动切换,当然可以不用viewpager了,也就不需要fragmentPagerAdapter了(纯手打,如果单词错了勿怪),使用fragmentmanager+frameLayout动态显示隐藏fragment,Activity代码在后面,先让我啰嗦完:

上一个项目使用的TabHost+FrameLayout+Fragment,对于Fragment的生命周期方法的执行有了一定的认识,在BaseFragment中做了详细记录,如下:

public abstract class BaseFragment extends Fragment {
    protected View rootView;
    public Context mContext;
    private boolean isCacheView=true;//是否缓存view

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        isCacheView = setISCacheView();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (null!=rootView && isCacheView) {
            ViewGroup parent = (ViewGroup) rootView.getParent();
            if (parent != null) {
                parent.removeView(rootView);
            }
        }else {
            rootView = loadView(inflater);
        }
        bindView(rootView);
        return rootView;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        LogUtils.w(this.getClass().getSimpleName()+"onViewCreated");
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //每次切换fragment都会调用
        LogUtils.w(this.getClass().getSimpleName()+"onActivityCreated");
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        LogUtils.w(this.getClass().getSimpleName()+"onDestroyView");
    }

    /**
     * 子类必须实现,载入自己的布局文件
     * 如果缓存view,则只会执行一次
     * @param inflater
     * @return
     */
    protected abstract View loadView(LayoutInflater inflater);

    /**
     * 子类必须实现,每次显示fragment时更新view
     * 不管缓存与否,每次都执行
     * @param rootView
     */
    protected abstract void bindView(View rootView);

    public boolean setISCacheView(){
        return true;
    }

    public View getView(){
        return rootView;
    }

    /**
     * 在该方法中才可以使用mContext
     */
    public void loadData(){};

    /**
     * 修改titleBar标题
     * @param s
     */
    public void setActivityTitle(String s){
        if (null!=mContext){
            BaseActivity activity = (BaseActivity) mContext;
            activity.setTitle(s);
        }
    }

    public void showProgressBar(){
        if (null!=mContext){
            MainActivity activity = (MainActivity) mContext;
            activity.showProgress();
        }
    }

    public void hideProgressBar(){
        if (null!=mContext){
            MainActivity activity = (MainActivity) mContext;
            activity.hideProgress();
        }
    }
    public void increaseProgress(){
        if (null!=mContext){
            MainActivity activity = (MainActivity) mContext;
            activity.increateProgress();
        }
    }
}

当前项目无脑的把上个项目的基类拷贝过来,想当然的以为使用FragmentManager自己管理fragment,其生命周期方法也一样,然后我在bindView(View rootView)方法里改变MainActivity内toolBar的标题,实现切换fragment时,标题也切换。但是并没有,切换fragment时,周期方法没有如期回调。
这里讲的比我清楚http://blog.csdn.net/a910626/article/details/46016887不同的是我fragment使用了tag标记,添加前判断是否存在,存在则弹出,不会重复创建。

public class MainActivity extends BaseActivity implements OnTabSelectListener {

    private FragmentManager fragmentManager;
    private ArrayList<String> fragmentTags;
    private int currIndex;
    private static final String CURR_INDEX = "currIndex";
    private BottomBar bottomBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fragmentManager = getSupportFragmentManager();
        initToolBar();
        initData(savedInstanceState);
        initView();
    }

    private void initView() {
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        bottomBar = (BottomBar) findViewById(R.id.bottomBar);
        bottomBar.setOnTabSelectListener(this);
        bottomBar.setTabSelectionInterceptor(new TabSelectionInterceptor() {
            @Override
            public boolean shouldInterceptTabSelection(@IdRes int oldTabId, @IdRes int newTabId) {
                if (oldTabId == R.id.tab_favorites&&newTabId==R.id.tab_friends)
                    return true;
                return false;
            }
        });
        showFragment();
    }

    private void initData(Bundle savedInstanceState) {
        fragmentTags = new ArrayList<>(Arrays.asList("HomeFragment", "ImFragment", "InterestFragment"));
        currIndex = 0;
        if(savedInstanceState != null) {
            currIndex = savedInstanceState.getInt(CURR_INDEX);
            hideSavedFragment();
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(CURR_INDEX, currIndex);
    }

    private void hideSavedFragment() {
        Fragment fragment = fragmentManager.findFragmentByTag(fragmentTags.get(currIndex));
        if(fragment != null) {
            fragmentManager.beginTransaction().hide(fragment).commit();
        }
    }

    private void showFragment() {
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        Fragment fragment = fragmentManager.findFragmentByTag(fragmentTags.get(currIndex));
        if(fragment == null) {
            fragment = FragmentFactory.createFragment(currIndex);
        }
        for (int i = 0; i < fragmentTags.size(); i++) {
            Fragment f = fragmentManager.findFragmentByTag(fragmentTags.get(i));
            if(f != null && f.isAdded()) {
                fragmentTransaction.hide(f);
            }
        }
        if (fragment.isAdded()) {
            fragmentTransaction.show(fragment);
        } else {
            fragmentTransaction.add(R.id.fragment_container, fragment, fragmentTags.get(currIndex));
        }
        fragmentTransaction.commitAllowingStateLoss();
        fragmentManager.executePendingTransactions();
    }

    @Override
    public String returnToolBarTitle() {
        return "测试";
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onTabSelected(@IdRes int tabId) {
        switch (tabId){
            case R.id.tab_favorites:
                currIndex = 0;
                BottomBarTab nearby = bottomBar.getTabWithId(R.id.tab_nearby);
                nearby.setBadgeCount(5);
                break;
            case R.id.tab_nearby:
                currIndex = 1;
                break;
            case R.id.tab_friends:
                currIndex = 2;
                break;
            default:
                break;
        }
        showFragment();
    }
}

好人做到底,布局文件

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.vmove.ecg.activity.MainActivity">
    <include
        layout="@layout/include_toolbar"/>
    <FrameLayout
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:background="@color/gray_white"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
    <com.roughike.bottombar.BottomBar
        android:id="@+id/bottomBar"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_gravity="bottom"
        app:bb_behavior="shy|shifting"
        app:bb_tabXmlResource="@xml/bottombar_tabs" />

</android.support.design.widget.CoordinatorLayout>

toolbar的布局懒得贴了,BaseActivity相信大家都有,里面有个ActivityManager,保存Activity的List。

总结一下,不管使用那种结构来显示fragment,其本质都是使用fragmentmanager管理fragment,只是有些现成的工具,比如TabHost、FragmentPagerAdapter内部使用fragmentmanager帮你管理了,使生命周期方法与Activity的同步,如果要自己写,也无可厚非。君子性非异也,善假于物也。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android开发中,Fragment是一个可重用的UI部分,它可以独立于Activity存在,并且可以根据需要添加到不同的Activity中。Fragment有自己的生命周期管理,这包括一系列的方法,用于描述Fragment从创建、显示、活跃到销毁的整个过程。 1. **onCreate()**: 当Fragment实例被创建时调用,这是初始化阶段,可以在此设置基本属性和数据。 2. **onCreateView()**: 如果Fragment没有预先创建视图,这个方法会被调用来生成视图。返回null则会使用默认布局。 3. **onStart()**: 当Fragment成为活动焦点或可见时调用,可以在这里开始执行耗时操作。 4. **onResume()**: 当Fragment变为活动的前景或者用户正在交互时,这个方法会被调用,意味着它是完全活跃的。 5. **onPause()**: 当Fragment不再接收用户交互或成为活动焦点时,但依然可见时,这个方法会被调用。 6. **onStop()**: 当Fragment失去焦点并且不处于可见状态时,例如切换到其他Activity,这个方法会被调用。 7. **onDestroyView()**: 当Fragment的视图不再需要时,这个方法会被调用,通常在onPause之后。 8. **onSaveInstanceState()**: 在onPause或onStop之前调用,用于保存Fragment的状态,以便在恢复时使用。 9. **onDestroy()**: 当Fragment被系统卸载,不再需要内存时,这个方法会被调用。 10. **onActivityCreated()**: 当Fragment的视图已经创建完毕,并且所有的依赖项都可用时,这个方法会被调用。 11. **onDestroyView()**: 视图销毁后调用,释放资源。 12. **onDetach()**: 当Fragment从其宿主Activity中分离出来时,这个方法会被调用,通常发生在用户切换回其他Activity时。 理解Fragment生命周期对于管理其行为、数据和资源至关重要。开发者可以根据这些阶段进行必要的资源管理、数据保存和状态更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值