fragment生命周期_从一个fragment到另一个fragment的生命周期 - CSDN
精华内容
参与话题
  • Fragment生命周期

    2018-08-08 22:49:47
    Fragment优点: 1、模块化:不需要把所有代码都写在activity中 2、可重用:多个activity可重用一个fragement 3、可适配:可以根据屏幕的尺寸,屏幕方向,方便的实现不同的布局   Fragment官方定义: A ...

    Fragment优点:

    1、模块化:不需要把所有代码都写在activity中

    2、可重用:多个activity可重用一个fragement

    3、可适配:可以根据屏幕的尺寸,屏幕方向,方便的实现不同的布局

     

    Fragment官方定义:

    A Fragment represents a behavior or a portion of user interface in an Activity. You can combine multiple fragments in a single activity to build a multi-pane UI and reuse a fragment in multiple activities. You can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running.

    从该定义知,fragement是依赖activity的不能独立存在,一个activity可以加载多个fragment,一个fragment可以被多个activity重用,fragement有自己的生命周期并能接收事件,能够在activity运行时动态的增删fragement

     

    Fragmengt使用过程中的常见类:

    1. Fragement

    FragmentManager:管理和维护Fragement,为抽象类,具体实现类为FragmentManagerImpl

    1. FragmentTransaction:fragement事务管理类,对Fragment的添加、删除等操作都需要通过事务方式进行,为抽象类,具体实现类是BackStackRecord

     

    Fragment的一些常用派生类

    DialogFragment显示一个浮动的对话框。使用这个类创建对话框是替代activity创建对话框的最佳选择。因为可以把fragmentdialog放入到activity的返回栈中,使用户能再返回到这个对话框。

    ListFragment:显示一个列表控件,就像ListActivity类,它提供了很多管理列表的方法,比如onListItemClick()方法响应click事件。

    PreferenceFragment显示一个由Preference对象组成的列表,与PreferenceActivity相同。它用于为程序创建设置”activity

     

    Fragment生命周期:

    setUserVisibleHint():设置Fragment可见或者不可见时会调用此方法。在该方法里面可以通过调用getUserVisibleHint()获得Fragment的状态是可见还是不可见的,如果可见则进行懒加载操作。
    onAttach():执行该方法时,FragmentActivity已经完成绑定,该方法有一个Activity类型的参数,代表绑定的Activity,这时候你可以执行诸如mActivity = activity的操作。
    onCreate():初始化Fragment,可通过参数savedInstanceState获取之前保存的值。
    onCreateView():初始化Fragment的布局。加载布局和findViewById的操作通常在此函数内完成,但是不建议执行耗时的操作,比如读取数据库数据列表。
    onActivityCreated():执行该方法时,与Fragment绑定的ActivityonCreate方法已经执行完成并返回,在该方法内可以进行与Activity交互的UI操作,所以在该方法之前ActivityonCreate方法并未执行完成,如果提前进行交互操作,会引发空指针异常。
    onStart():执行该方法时,Fragment由不可见变为可见状态。
    onResume():执行该方法时,Fragment处于活动状态,用户可与之交互。
    onPause():执行该方法时,Fragment处于暂停状态,但依然可见,用户不能与之交互。
    onSaveInstanceState():保存当前Fragment的状态。该方法会自动保存Fragment的状态,比如EditText键入的文本,即使Fragment被回收又重新创建,一样能恢复EditText之前键入的文本。
    onStop():执行该方法时,Fragment完全不可见。
    onDestroyView():销毁与Fragment有关的视图,但未与Activity解除绑定,依然可以通过onCreateView方法重新创建视图。通常在ViewPager+Fragment的方式下会调用此方法。
    onDestroy():销毁Fragment。通常按Back键退出或者Fragment被回收时调用此方法。
    onDetach():解除与Activity的绑定。在onDestroy方法之后调用。

    展开全文
  • 理解Fragment生命周期

    万次阅读 多人点赞 2012-11-29 14:33:01
    官网帮助文档链接:  ... 主要看两张图,和跑代码 一,Fragment的生命周    二,与Activity生命周期的对比   场景演示 : 切换到该Fragment 11-29 14:26:35.095: D/AppListFragmen

    官网帮助文档链接:
     http://developer.android.com/guide/components/fragments.html

    主要看两张图,和跑代码

    一,Fragment的生命周 

              

    二,与Activity生命周期的对比

         

    场景演示 : 切换到该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


    比Activity多了一些生命周期,完整和Activity对接上,大家好好利用。

    展开全文
  • Fragment常用知识积累!

    Fragment API(镜像地址):

    http://androiddoc.qiniudn.com/reference/android/support/v4/app/Fragment.html


    Fragment/Activity生命周期图



    Fragment状态变化常用方法

    1. onHiddenChanged(boolean hidden)

    Activity内部通过show和hide方法切换Fragment时,引发的状态变迁。

    2. setUserVisibleHint(boolean isVisibleToUser)

    ViewPager和Fragment一起使用时,ViewPager就是利用这个方法控制Fragment的显示与隐藏的,所以通过这个方法可以实现ViewPager中Fragment的懒加载模式。

    3. isVisible()

    如果该Fragment对象对用户可见,那么就返回true。这就意味着:1.已经被添加到Activity中;2.它的View对象已经被绑定到窗口中;3.没有被隐藏。

    isVisible()方法需要注意和getUserVisibleHint()方法的区别。

    isVisible() 方法可用于fragment的 onResume() 生命周期方法中,用于判断当app从其他界面进入(初次创建或者返回)fragment所attach的activity时,当前Fragment是否可见。配合使用 onHiddenChanged方法,常用于Fragment界面的刷新。

    特别说明:存在这样一种情况,当从其他 Activity 通过setResult方法返回到 包含多个Fragment的Activity,并且在目标Activity的onActivityResult方法中指定显示处于隐藏状态的一个Fragment时,如果仅仅依据isVisible方法是无法区分所要显示的Fragment的onHiddenChanged和onResume方法,因为onActivityResult方法要优先于onResume方法,所以此时需要用到 isResumed() 方法来限制界面刷新的调用:

        @Override
        public void onResume() {
            super.onResume();
            if (isVisible()){
                //界面刷新操作,如网络请求
            }
        }
    
        @Override
        public void onHiddenChanged(boolean hidden) {
            super.onHiddenChanged(hidden);
            if (isVisible() && isResumed()){
                //界面刷新操作,如网络请求
            }
        }
    


    4. setArguments(Bundle args)


    Fragment使用常见问题

    1. Fragment切换导致UI重叠问题

    问题演示:

       

    问题模拟重现

    1.首先打开,默认选中的是第一个tab,如上面的一张图片正常那样。
    2.切换到tab2,并把tab1 hide掉;
    3.再切回到tab1,并不会触发tab1对应fragment的任何生命周期;
    4.然后home键进入后台,我在activity的onPause()中手动对IndexFragment赋空,模拟长时间后台,系统销毁了该引用:IndexFragment=null;
    5.再次启动,其实tab1 的fragment实例在内存中还在,只是他的引用被销毁了。
    6.再切到tab2,这里其实是先把tab1的hide,在show tab2,但是tab1 的fragment引用为空,所以无法hide,就出现了tab2叠在tab1上的花屏情况。
    7.再切到tab1,tab1就会重复创建对象。

    问题分析

    fragment的切换有两种方式:

    1. replace方式

    transaction.replace(R.id.content, IndexFragment);

    使用replace方式不会出现上述问题,但是会重复创建对象,每次replace会把生命周期全部执行一遍,如果在这些生命周期函数 里拉取数据的话,就会不断重复的加载刷新数据。

    2. add - hide - show方式

    transaction.add(R.id.content, IndexFragment); transaction.hide(otherfragment); transaction.show(thisfragment);

    public class TestFragmentTab extends FragmentActivity {
    	
    	private static final String TAG = "TestFragmentTab";
    	
    	private int tabIds[] = new int[]{
    			R.id.home_tab_main,
    			R.id.home_tab_search,
    			R.id.home_tab_category,
    	};
    	
    	private FragmentTab1 mTab1;
    	private FragmentTab2 mTab2;
    	private FragmentTab3 mTab3;
    
    	@Override
    	public void onAttachFragment(Fragment fragment) {
    		// TODO Auto-generated method stub
    		super.onAttachFragment(fragment);
    		Log.d(TAG,"onAttachFragment");
    	}
    
    	@Override
    	protected void onDestroy() {
    		// TODO Auto-generated method stub
    		super.onDestroy();
    		Log.d(TAG,"onDestroy");
    	}
    
    	@Override
    	protected void onPause() {
    		// TODO Auto-generated method stub
    		super.onPause();
    		Log.d(TAG,"onPause");
    	}
    
    	@Override
    	protected void onResume() {
    		// TODO Auto-generated method stub
    		super.onResume();
    		Log.d(TAG,"onResume");
    	}
    
    	@Override
    	protected void onStart() {
    		// TODO Auto-generated method stub
    		super.onStart();
    		Log.d(TAG,"onStart");
    	}
    
    	@Override
    	protected void onStop() {
    		// TODO Auto-generated method stub
    		super.onStop();
    		Log.d(TAG,"onStop");
    	}
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		super.onCreate(savedInstanceState);
    		Log.d(TAG,"onCreate");
    		setContentView(R.layout.layout_test_fragment_tab);
    		
    		RadioGroup tabButtonGroup = (RadioGroup) findViewById(R.id.bottom_bar);
    		tabButtonGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    			
    			@Override
    			public void onCheckedChanged(RadioGroup group, int checkedId) {
    				// TODO Auto-generated method stub
    				for (int i = 0; i < tabIds.length; i++) {
    					if (tabIds[i] == checkedId) {
    						setSelection(i);
    						break;
    					}
    				}
    			}
    		});
    		
    		setSelection(0);
    	}
    	
    	private void setSelection(int position){
    		
    		FragmentManager fm = getSupportFragmentManager();
    		FragmentTransaction ft = fm.beginTransaction();
    		hideAllFragments(ft);
    		
    		switch (position) {
    		case 0:
    			if (mTab1 == null) {
    				mTab1 = new FragmentTab1();
    				ft.add(R.id.content, mTab1);
    			}else {
    				ft.show(mTab1);
    			}
    			break;
    			
    		case 1:
    			if (mTab2 == null) {
    				mTab2 = new FragmentTab2();
    				ft.add(R.id.content, mTab2);
    			}else {
    				ft.show(mTab2);
    			}
    			break;
    			
    		case 2:
    			if (mTab3 == null) {
    				mTab3 = new FragmentTab3();
    				ft.add(R.id.content, mTab3);
    			}else {
    				ft.show(mTab3);
    			}
    			break;
    
    		default:
    			break;
    		}
    		
    		ft.commit();
    	}
    	
    	private void hideAllFragments(FragmentTransaction ft){
    		if (mTab1 != null) {
    			ft.hide(mTab1);
    		}
    		
    		if (mTab2 != null) {
    			ft.hide(mTab2);
    		}
    		
    		if (mTab3 != null) {
    			ft.hide(mTab3);
    		}
    	}
    
    }

    使用第二种方式做Fragment的切换时,经常会出现上图所示Fragment重叠问题。直接back键退出应用再进入时,则没有出现该问题。当应用被强行关闭后(通过手机管家软件手动强关,或系统为节省内存自动关闭应用),再次进入应用时,每次都会出现这种花屏现象。

    通过分析发现,正常back键退出应用时,Activity及所属的Fragment对象均会被销毁,因此再次进入时会在切换到Tab时创建对应的Fragment对象。
    但是当强行关闭应用后,Activity虽然被回收,但Fragment对象仍然保持,再次进入应用时,系统会分别调用Fragment的onAttach方法将其附加到Activity上,后面会分别调用两个fragment的onCreateView方法,因此这两个Fragment对应的View层次结构都会加到Activity的View层次中。
    虽然切换Fragment时会把所有fragment先隐藏再显示选中的对象,但由于此时Activity中Fragment对象的成员变量还未初始化,因此会再次实例化fragment对象,之后add、show及hide的都是在第二次创建的对象上操作的,而之前被保持的fragment对象的视图层次已经反映到Activity视图中并且不会被hide,因此发生了上述重叠现象。

    解决办法有三种:

    第一种:

    在Activity的onAttachFragment方法中,有一个fragment参数,它就是onAttach方法对应的Fragment对象,
    通过判断这个fragment对象,如果属于我们的FragmentTabX类并且该类还未被实例化过,则将Activity的成员变量mFragmentTabX指向该fragment对象,这样就可以在原来的fragment对象上操作add/show/hide,因此不会有重叠现象

    @Override
    	public void onAttachFragment(Fragment fragment) {
    		// TODO Auto-generated method stub
    		super.onAttachFragment(fragment);
    		Log.d(TAG,"onAttachFragment");
    		
    		if (mTab1 == null && fragment instanceof FragmentTab1) {
    			mTab1 = (FragmentTab1)fragment;
    		}else if (mTab2 == null && fragment instanceof FragmentTab2) {
    			mTab2 = (FragmentTab2)fragment;
    		}else if (mTab3 == null && fragment instanceof FragmentTab3) {
    			mTab3 = (FragmentTab3)fragment;
    		}
    	}

    第二种:

    调用三个参数的add函数,添加Tag参数用于标记:

    transaction.add(R.id.content, IndexFragment,”Tab1″);

    然后,在fragment初始化前,添加引用判断,找打对应的引用,如果依旧为空,再调用fragment构造函数进行初始化:

    IndexFragment=FragmentManager.findFragmentByTag(“Tab1″);

    第三种:

    在进入onCreate函数时,先去判断savedInstanceState是否为null,如果不为null,则表示里面有保存这四个fragment。则不再重新去add这四个fragment,而是通过Tag从前保存的数据中直接去读取。

            FragmentManager fManager;
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		fManager = getFragmentManager();
    		if (savedInstanceState != null) {
    			allFrg = (AllOfficialAccountFragment) fManager.findFragmentByTag("allFrg");
    			movieFrg = (MovieOfficialAccountFragment) fManager.findFragmentByTag("movieFrg");
    			newsFrg = (NewsOfficialAccountFragment) fManager.findFragmentByTag("newsFrg");
    			otherFrg = (OtherOfficialAccountFragment) fManager.findFragmentByTag("otherFrg");			
    		}
    		super.onCreate(savedInstanceState);		
    	}


    2.Fragment not attached to Activity异常

    出现该问题,主要是因为在Fragment还没有被关联到Activity的时候或者被Attach的Activity已经destroy了的时候,调用了需要上下文Context的函数,常见的如fragment的getResource()方法。解决办法主要有:

    一:将调用的代码移动到onStart()方法中;

    三:使用被Attach的Activity的相应方法,如getActivity().getResource...等;

    二:在调用的代码前添加Fragment的isAdd()方法进行判断,推荐使用这种方式!


    3. Fragment中onActivityResult()注意问题

    通常,我们会在FragmentActivity中嵌套一层Fragment使用,甚至在Fragment中再次层层嵌套Fragment,此时,会出现第二层及更深层次的子Fragment对象无法接收到onActivityResult()事件。

    查看FragmentActivity源码:

    	 @Override 
    	 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    		 mFragments.noteStateNotSaved(); 
    	     int index = requestCode>>16; 
    	     if (index != 0) { 
    	              index--; 
    	              if (mFragments.mActive == null || index < 0 || index >= mFragments.mActive.size()) { 
    	                   Log.w(TAG, "Activity result fragment index out of range: 0x" 
    	                           + Integer.toHexString(requestCode)); 
    	                   return; 
    	               } 
    	               Fragment frag = mFragments.mActive.get(index); 
    	               if (frag == null) { 
    	                   Log.w(TAG, "Activity result no fragment exists for index: 0x" 
    	                           + Integer.toHexString(requestCode)); 
    	               } else { 
    	                   frag.onActivityResult(requestCode&0xffff, resultCode, data); 
    	               } 
    	               return; 
    		} 
    	             
    	    super.onActivityResult(requestCode, resultCode, data); 
    	}

    可以看出,FragmentActivity没有处理嵌套Fragment的情况,也就是说,只是回调到第一级的Fragment中,然后没有继续分发下去。

    所以,我们需要在第一级的Fragment的onActivityResult()中控制分发onActivityResult事件。


    4. FragmentTransaction的commit问题

    FragmentTransaction有commit()和commitAllowingStateLoss()两个提交方法,通过源码看他们的区别:

    commit():

    Schedules a commit of this transaction. The commit does not happen immediately; it will be scheduled as work on the main thread to be done the next time that thread is ready. 
    A transaction can only be committed with this method prior to its containing activity saving its state. If the commit is attempted after that point, an exception will be thrown. This is because the state after the commit can be lost if the activity needs to be restored from its state. See commitAllowingStateLoss() for situations where it may be okay to lose the commit.
    
    Returns:
    Returns the identifier of this transaction's back stack entry, if addToBackStack(String) had been called. Otherwise, returns a negative number.

    commitAllowingStateLoss():

    Like commit but allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
    

    顾名思义,可以看出,使用commit()方法,如果在Activity保存状态后发生了commit行为,将抛出异常:

    java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    	at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)
    	at android.support.v4.app.FragmentManagerImpl.enqueueAction(Unknown Source)
    	at android.support.v4.app.BackStackRecord.commitInternal(Unknown Source)
    	at android.support.v4.app.BackStackRecord.commit(Unknown Source)

    而commitAllowingStateLoss()方法允许这种调用,但是当Activity回复状态时,之前fragment的提交状态将丢失。所以,如果你允许这种丢失commit状态的话,可以使用commitAllowingStateLoss()。

    参考文章:FragmentTransaction的commit和commitAllowingStateLoss的区别


    参考地址:

    Android Fragment 你应该知道的一切

    Android解惑 - 为什么要用Fragment.setArguments(Bundle bundle)来传递参数

    Android Fragment 真正的完全解析(上)

    Android Fragment 真正的完全解析(下)





    展开全文
  • Fragment 生命周期

    千次阅读 2018-05-30 15:07:51
    深入理解Fragment进阶系列(一):生命周期详解 本系列是介绍Fragment相关的一些内容,由浅入深。 1. 深入理解Fragment进阶系列(一):生命周期详解 Fragment最初出现在Android3.0,用来解决大小屏设备适配...




    深入理解Fragment进阶系列(一):生命周期详解

    本系列是介绍Fragment相关的一些内容,由浅入深。

    1. 深入理解Fragment进阶系列(一):生命周期详解

    Fragment最初出现在Android3.0,用来解决大小屏设备适配问题。Fragment不能单独存在,必须依附于Activity(Android4.2起Fragment也可以嵌套Fragment)。Fragment有一套自己的生命周期,相应的也是依赖Activity的生命周期( 例如,当 Activity 暂停时,其中的所有Fragment也会暂停;当 Activity 被销毁时,所有Fragment也会被销毁)。一个Activity可以使用多个Fragment,一个Fragment也可以附属在多个Activity上,十分灵活。

    对于低版本可以使用V4库,需要注意的是使用V4的Fragment,Activity要继承FragmentActivity,获取FragmentManger要使用getSupportFragmentManger()。

    既然Fragment拥有自己的生命周期,本文就来详细的讲一讲相关的内容。主要包括以下几个方面。

    1. Fragment的生命周期
    2. Activity 生命周期对Fragment生命周期的影响
    3. Fragment相关操作对生命周期的影响
    4. 应用被系统回收对生命周期的影响
    5. ViewPager对Fragment生命周期的影响
    6. 判断Fragment是否可见

    Fragment的生命周期

    说起Fragment的生命周期,就不得不放一张十分经典的官方图。
    片段的生命周期(其 Activity 运行时)

    emmmm… 乍一看是不是有一张似曾相识的感觉,Fragment的生命周期大体上和Activity类似,我们先对每个回调方法都具体的介绍一下。

    Fragment的生命周期是和其关联的Activity有关,在这里为了方便叙述之后说的Activity都特指Fragment相关联的Activity

    1. onAttach(Context context):在Fragment和Activity关联上的时候调用,且仅调用一次。在该回调中我们可以将context转化为Activity保存下来,从而避免后期频繁调用getAtivity()获取Activity的局面,避免了在某些情况下getAtivity()为空的异常(Activity和Fragment分离的情况下)。同时也可以在该回调中将传入的Arguments提取并解析,在这里强烈推荐通过setArguments给Fragment传参数,因为在应用被系统回收时Fragment不会保存相关属性,具体之后会讲解。

    2. onCreate:在最初创建Fragment的时候会调用,和Activity的onCreate类似。

    3. View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState):在准备绘制Fragment界面时调用,返回值为Fragment要绘制布局的根视图,当然也可以返回null。注意使用inflater构建View时一定要将attachToRoot指明false,因为Fragment会自动将视图添加到container中,attachToRoot为true会重复添加报错。onCreateView并不是一定会被调用,当添加的是没有界面的Fragment就不会调用,比如调用FragmentTransaction的 add(Fragment fragment, String tag)方法。

    4. onActivityCreated :在Activity的onCreated执行完时会调用。

    5. onStart() :Fragment对用户可见的时候调用,前提是Activity已经started。

    6. onResume():Fragment和用户之前可交互时会调用,前提是Activity已经resumed。

    7. onPause():Fragment和用户之前不可交互时会调用。

    8. onStop():Fragment不可见时会调用。

    9. onDestroyView():在移除Fragment相关视图层级时调用。

    10. onDestroy():最终清楚Fragment状态时会调用。

    11. onDetach():Fragment和Activity解除关联时调用。

    图中有一条从onDestroyView指向onCreatedView的线,意思是Fragment从back栈(存放Fragment的栈)回到前台时经历的生命周期。


    Activity 生命周期对Fragment生命周期的影响

    将Fragment生命周期中每个回调单独讲完之后,下面就来看看Fragment生命周期和Activity生命周期之前的联系,这里也有一张十分经典的官方图。

    Activity 生命周期对片段生命周期的影响

    可以十分明了的看到,当Activity处于不同生命周期时Fragment生命周期的流程。需要关注一下两者生命周期顺序问题,其中onCreate、onStart、onResume都是Activity先调用之后才是Fragment,onPause、onStop、onDestroy(在Fragment中是onDetach),是先Fragment调用之后才是Activity。其他的就不展开说了,图十分明了。


    Fragment相关操作对生命周期的影响

    添加Fragment可以分为静态添加和动态添加两大类。静态添加是在XML中直接添加Fragment,简单方便,缺点是添加之后不能在删除。动态添加是在代码中FragmentManger使用一系列FragmentTransaction事务操作动态控制,灵活多变。一般都是使用动态添加,下面就讲讲动态添加有关的生命周期。

    1. add:onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume

    2. remove:onPause->onStop->onDestroyView->onDestroy->onDetach

    3. show:onHiddenChanged(boolean hidden) hidden为false

    4. hide:onHiddenChanged(boolean hidden) hidden为true

    5. replace:旧Fragment的remove生命周期->新Fragment的add生命周期

    6. replace+addToBackStack:onPause->onStop->onDestroyView->新Fragment的add生命周期
      之后点击back:新Fragment的remove->onCreateView->onViewCreated->onActivityCreated->onStart->onResume 就是第一张图的线

    7. detach:onPause->onStop->onDestroyView 可以看到只是视图被移除,Fragment关联状态还是不变,还是处于FragmentManger的管理下

    8. FragmentTransaction.attach(Fragment var1):onStart->onResume->onCreateView

    注意:Fragment的show和hide仅仅是将Fragment视图设置为是否可见,不会调用任何生命周期。该Fragment的生命周期还是会随着Activity的生命周期变化而变化,例如FragmentA hide、FragmentB show,点击Home A和B都会onPause->onStop


    应用被系统回收对生命周期的影响

    应用被回收一般都是后台应用,所以生命周期是从onDestroyView开始

    • 单独一个Fragment
      onDestroyView->onDestroy->onDetach->add生命周期

    • Fragment A hide,Fragment B show
      A.onDestroyView->A.onDestroy->A.onDetach->B.onDestroyView->B.onDestroy->B.onDetach->A.onAttach->A.onCreate->B.onAttach->B.onCreate->A.onCreateView->A.onActivityCreated->B.onCreateView->B.onActivityCreated->A.onStart->B.onStart->A.onResume->B.onResume

    为了防止在系统回收应用情况下,再次进不出错,强烈建议大家
    1. 使用setArguments(Bundle bundle)方法传递参数。对于常规变量想必大家都已经十分熟练了,就不细说了。这里主要强调View变量和接口变量,View变量可以通过传入View的id,之后再通过id获取view的方法来实现。接口可以通过Activity实现,Fragment强转Activity实现。
    2. addFragment之前先通过findFragmentById判断是否添加过避免重复添加,如使用FragmentAdapter可以在onSaveInstanceState存储相应Fragment.getTag


    ViewPager对Fragment生命周期的影响

    ViewPager+Fragment已经是比较常见的组合,一般搭配ViewPager的FragmentPagerAdapter或FragmentStatePagerAdapter使用。不过ViewPager为了防止滑动出现卡顿,有一个缓存机制,默认情况下ViewPager会创建并缓存当前页面左右两边的页面(如Fragment)。此时左右两个Fragment都会执行从onAttach->….->onResume的生命周期,明明Fragment没有显示却已经到onResume了,在某些情况下会出现问题。比如数据的加载时机、判断Fragment是否可见等。

    可以通过ViewPager的setOffscreenPageLimit(int limit)来设置ViewPager缓存个数,最小是1个即便我们设置为0,源码如下。

     public void setOffscreenPageLimit(int limit) {
            if (limit < DEFAULT_OFFSCREEN_PAGES) { 
            //     private static final int DEFAULT_OFFSCREEN_PAGES = 1;
                Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                        + DEFAULT_OFFSCREEN_PAGES);
                limit = DEFAULT_OFFSCREEN_PAGES;
            }
            if (limit != mOffscreenPageLimit) {
                mOffscreenPageLimit = limit;
                populate();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    懒加载

    如果不对数据加载时机做处理,使用ViewPager默认会将左右两个Fragment的数据也加载,当数据加载比较消耗资源会影响性能。我们可以对加载时机做调整使用懒加载,具体就是在Fragment真正可见时才加载数据。

    在Fragment切换时候会调用setUserVisibleHint(boolean isVisibleToUser),isVisibleToUser表示是否对用户可见。setUserVisibleHint不单单在Fragment切换时调用,在onAttach之前都会调用一次此时isVisibleToUser为false,在onCreateView之前会调用一次此时isVisibleToUser的值为当前Fragment是否可见,之后就是在Fragment切换的时候会调用。

    因为setUserVisibleHint会在onCreateView之前调用,如果数据加载涉及到view相关的操作别忘了设置一个变量来判断一下视图是否已经创建好。


    判断Fragment是否可见

    判断Fragment是否可见最常见就是用在埋点上了,不同情况下判断方法并不相同,主要分为两大类。

    在Activity中使用

    先上一段在Fragment可见的埋点代码

     @Override
        public void onResume() {
            super.onResume();
            // 注意这个判断 isHidden()是当前Fragment是否隐藏
            if (!isHidden()) {
                reportPageShow();
            }
        }
    
    @Override
        public void onHiddenChanged(boolean hidden) {
            super.onHiddenChanged(hidden);
            if (!hidden) {
                reportPageShow();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在添加Fragment或者从Fragment和其他Activity相互跳转的时候,都会调用onResume和onStop。如果是show或在hide Fragment的时候会调用onHiddenChanged。

    不知道大家有没有发现在onResume的时候判断了一下当前Fragment是否被隐藏了,这个判断是有说法的。之前说过show和hide仅仅是将Fragment视图设置为是否可见,不会影响其生命周期。还原场景,如果Fragment A hide,Fragment B show,然后Activity从后台到前台是A和B的onResume都会被调用!所以要在onResume判断一下当前Fragment是否被隐藏,当然如果没有用到show和hide,只使用简单的onResume和onStop也没问题。

    在ViewPager中使用

    之前说过ViewPager为了防止滑动出现卡顿,有一个缓存机制,默认情况下ViewPager会创建并缓存当前页面左右两边的页面(如Fragment)。左右两个Fragment都会执行从onAttach->….->onResume的生命周期,此时Fragment的生命周期已经不可靠。不过在Fragment切换的时候会调用setUserVisibleHint(boolean isVisibleToUser),isVisibleToUser表示是否对用户可见。因此可以在setUserVisibleHint进行Fragment是否可见的判断。

     @Override
        public void setUserVisibleHint(boolean isVisibleToUser) {
            super.setUserVisibleHint(isVisibleToUser);
            if (isVisibleToUser) {
                reportPageShow();
            }
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    看完上面的内容想必对Fragment的生命周期了解有所加深,下面一篇将会从源码来分析一下Fragment相关的内容



    展开全文
  • Fragment 整个生命周期演示

    千次阅读 2014-05-21 17:15:34
    生命周期主要体现在以下表中13个方法里,以下是按照Fragment从开始到销毁的先后执行顺序排序。   序号 方法名称 描述 1 public void onInflate(Activity activity, AttributeSet attrs,Bundle ...
  • Fragment生命周期详解

    2019-10-10 12:03:44
    序言 Fragment从Android v3.0版本开始引入的,随着界面布局的复杂化,处理起来也更加的复杂,...Fragment可以响应自己的输入事件,并拥有自己的生命周期,但它们的生命周期直接被其所属的Activity的生命周期控制。...
  • Fragment各种情况的生命周期

    千次阅读 2019-10-28 09:50:23
    Fragment生命周期方法: onAttach(): 完成Fragment和Activity的绑定,参数中的Activity即为要绑定的Activity,可以进行赋值等操作。 onCreate() : 完成Fragment的初始化 onCreateView() : 加载Fragment布局...
  • 浅谈 Fragment 生命周期

    万次阅读 2017-04-19 14:29:55
    版权声明:本文为博主原创文章,未经博主允许不得转载。 微博:厉圣杰 源码:AndroidDemo/Fragment ...Fragment 有自己的布局,有自己的生命周期,有自己的事件响应。 但 Fragment 又是依赖于 Activity 存在的,你可以
  • Fragment 在各种情况下的生命周期

    千次阅读 2017-10-10 14:22:49
    Fragment 应该是面试时大家经常会遇到的问题,所以今天拿出来跟大家分享一下,对于Fragment是如何产生的,已经Fragment是如何使用的,...这里我们主要把Fragment生命周期更加详细的介绍一下,有的人会说了,生命周
  • 最近纠结fragment切换生命周期执行,看到这边博客总结的很好,...首先,写一写关于Fragment生命周期的相关。先放上一张老图!! Fragment生命周期 Fragment 1 切换到 Fragment 2时生命周期变化 1、通过 add ...
  • Android Fragment 生命周期及回调方法

    千次阅读 2019-03-11 11:23:56
    Android Fragment 生命周期及回调方法 1.概述 基本概念:Fragment,简称碎片,片元。是Android 3.0(API 11)提出的,为了兼容低版本,support-v4库中也开发了一套Fragment API,最低兼容Android 1.6。 support-v4库...
  • Android Fragment 真正的完全解析(上)

    万次阅读 多人点赞 2016-08-10 19:34:33
    本篇博客力求为大家说明Fragment如何产生,什么是Fragment,Fragment生命周期,如何静态和动态的使用Fragment,Fragment回退栈,Fragment事务;以及Fragment的一些特殊用途,例如:没有布局的Frag
  • fragment hide/show 生命周期

    万次阅读 2014-11-23 16:55:28
    Fragment的使用越来越普遍了,掌握它的生命周期以及注意事项时非常有必要的,首先 All subclasses of Fragment must include a public empty constructor. The framework will often re-instantiate a fragment ...
  • 拥有Fragment的Activity的生命周期直接影响了其中的Fragment生命周期,这样,针对Activity的每一个生命周期的回调都会有一个类似的针对Fragment的回调。例如,当Activity收到onPause()回调时,在Activity中每个...
  • 总结:1、replace,加回退栈,Fragment不销毁,但是切换回销毁视图和重新创建视图。...隐藏和显示不走生命周期。1、Fragment采取replace方法替换、并加入回退栈。private void replaceFragment(in...
  • 前言Activity的生命周期都应该熟悉,Fragment其标准生命周期也仅比Activity多出一些流程,如onCreateView(),比较好理解。了解Activity、Fragment的基础知识可以先转头去看下我的博文:Android Fragment项目中使用及...
  • Fragment生命周期

    千次阅读 2017-02-06 09:32:34
    Fragment生命周期
  • 你的fragment们可以向activity的菜单(按Manu键时出现的东西)添加项,同时也可向动作栏(界面中顶部的那个区域)添加条目,这都需通过实现方法onCreateOptionManu()来完成。 你从fragment添加到菜单的任何条目,...
  • 【Android】【Fragment】Fragment生命周期

    千次阅读 2018-03-27 12:21:02
    保存 标签 2018-03-27 www.cnblogs.com/fajieyefu/p/6092465.html Fragment每个生命周期方法的意义、作用(注意红色的不是生命周期方法):setUserVisibleHint():设置Fragment...
  • Android Fragment---处理Fragment生命周期

    万次阅读 2012-02-19 19:01:24
    管理Fragment生命周期有点像管理Activity的生命周期,跟Activity一样,Fragment也存在三种状态: 恢复态: 这种状态下,Fragment显示在正在运行的Activity中。 暂停态: 这种状态下,另一个Activity在前台,...
1 2 3 4 5 ... 20
收藏数 30,838
精华内容 12,335
关键字:

fragment生命周期