Fragment篇——面试必问的Fragment的生命周期
来源:互联网 发布:制作情书的软件 编辑:程序博客网 时间:2024/05/22 00:46
Fragment的产生
Android 在 Android 3.0(API 级别 11)中引入了片段,主要是为了给大屏幕(如平板电脑)上更加动态和灵活的 UI 设计提供支持。但是大多数情况下,根据不同的使用情景我们并没有对平板应用使用fragment进行适配,所以更多的是我们把fragment作为一个可重复利用的模块化组件,利用它拥有自身生命周期回调,布局,行为等特性来对功能模块进行分离
Fragment的生命周期
一般来说,Activity管理Fragment已经做得非常好了,比如,锁屏,回到屏幕的时候,Fragment都是跟随Activity发生改变的。Fragment包含与Activity类似的生命周期,比如onCreate,onStart,onResume,onPause,onStop,onDestroy,下面是引用自Google开发者的图片,关于一个Fragment被添加时(动态/静态)的生命周期的变化
我们来看看fragment的生命周期都有什么作用
//系统在向 Activity 添加片段时调用的方法,附加之后才能够通过getActivity()获取Activity的上下文。public void onAttach(Context context)public void onCreate(Bundle savedInstanceState)//返回Fragment的布局public View onCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState)// 在 Activity 的 onCreate() 方法已返回时调用。public void onActivityCreated(@Nullable Bundle savedInstanceState)//在Activity的onStart之后调用public void onStart()//在Activity的onResume之后调用public void onResume()//在Activity的onPause之前调用public void onPause() //在Activity的onStop之前调用public void onStop()// 在移除与片段关联的视图层次结构时调用。public void onDestroyView()// 在Activity的onDestroy之前调用public void onDestroy()// 在取消片段与 Activity 的关联时调用。public void onDetach()
管理片段生命周期与管理 Activity 生命周期很相似。但是因为Fragment依附于Activity,所以很容易想象,关于Fragment创建的生命周期总是在Activity之后调用,关于Fragment销毁的生命周期总是在Activity之前调用。除此之外,在Activity需要重新创建的时候,fragment和activity一样可以通过onSaveInstanceState来保存状态,然后在onCreate,onCreateView或者onActivityCreated期间恢复状态。
对于Fragment的一些操作对生命周期的影响
// replace,FragmentA替换为FragmentB,在创建完B以后会先销毁A,再创建B的视图FragmentB: onAttachFragmentB: onCreate——————————————————————————FragmentA: onPauseFragmentA: onStopFragmentA: onDestroyViewFragmentA: onDestroyFragmentA: onDetach——————————————————————————FragmentB: onCreateViewFragmentB: onActivityCreatedFragmentB: onStartFragmentB: onResume// add,添加FragmentAFragmentA: onAttachFragmentA: onCreateFragmentA: onCreateViewFragmentA: onActivityCreatedFragmentA: onStartFragmentA: onResume//remove,移除FragmentAFragmentA: onPauseFragmentA: onStopFragmentA: onDestroyViewFragmentA: onDestroyFragmentA: onDetach//attach,从detach到attach状态FragmentA: onCreateViewFragmentA: onActivityCreatedFragmentA: onStartFragmentA: onResume//detach,从attach到detach状态FragmentA: onPauseFragmentA: onStopFragmentA: onDestroyView
注意:hide和show不会触发生命周期回调
给Fragment设置参数
使用setArguments,在创建Fragment的时候传递参数,然后在fragment的onCreate方法处获取参数,但是需要注意的是setArguments()方法必须在fragment创建以后,add之前调用。这样的好处是对Fragment的代码进行管理
//流行一种做法是使用静态方法newInstance()的方式来初始化Fragment public static CircleFragmetn newInstance(String str){ Bundle bundle = new Bundle(); bundle.putString("data", str); CircleFragmetn fragment = new CircleFragmetn(); fragment.setArguments(bundle); return fragment; }
没有UI的Fragment
可以添加没有UI的Fragment,使用add(Fragment,String)向Activity添加片段,由于它不与Activity布局的视图关联,所以不会触发onCreateView。通常没有UI的Fragment都是用于保存Activity的状态,或者借助setTargetFragment来控制其他fragment的UI变化,使用setRetainInstance()这个方法来告诉框架,当配置发生改变的时候,尝试保留这个fragment。SDK的APIdemos提供了范例
/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.apis.app; import com.example.android.apis.R; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; /** * This example shows how you can use a Fragment to easily propagate state * (such as threads) across activity instances when an activity needs to be * restarted due to, for example, a configuration change. This is a lot * easier than using the raw Activity.onRetainNonConfiguratinInstance() API. */ public class FragmentRetainInstance extends Activity { private static String TAG="FragmentRetainInstance"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // First time init, create the UI. if (savedInstanceState == null) { getFragmentManager().beginTransaction().add(android.R.id.content, new UiFragment()).commit(); } } /** * This is a fragment showing UI that will be updated from work done * in the retained fragment. */ public static class UiFragment extends Fragment { RetainedFragment mWorkFragment; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_retain_instance, container, false); // Watch for button clicks. Button button = (Button)v.findViewById(R.id.restart); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { mWorkFragment.restart(); } }); return v; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); FragmentManager fm = getFragmentManager(); // Check to see if we have retained the worker fragment. mWorkFragment = (RetainedFragment)fm.findFragmentByTag("work"); // If not retained (or first time running), we need to create it. if (mWorkFragment == null) { mWorkFragment = new RetainedFragment(); // Tell it who it is working with. mWorkFragment.setTargetFragment(this, 0); fm.beginTransaction().add(mWorkFragment, "work").commit(); } } } /** * This is the Fragment implementation that will be retained across * activity instances. It represents some ongoing work, here a thread * we have that sits around incrementing a progress indicator. */ public static class RetainedFragment extends Fragment { ProgressBar mProgressBar; int mPosition; boolean mReady = false; boolean mQuiting = false; /** * This is the thread that will do our work. It sits in a loop running * the progress up until it has reached the top, then stops and waits. */ final Thread mThread = new Thread() { @Override public void run() { // We'll figure the real value out later. int max = 10000; // This thread runs almost forever. while (true) { // Update our shared state with the UI. synchronized (this) { // Our thread is stopped if the UI is not ready // or it has completed its work. while (!mReady || mPosition >= max) { if (mQuiting) { return; } try { wait(); } catch (InterruptedException e) { } } // Now update the progress. Note it is important that // we touch the progress bar with the lock held, so it // doesn't disappear on us. mPosition++; max = mProgressBar.getMax(); mProgressBar.setProgress(mPosition); } // Normally we would be doing some work, but put a kludge // here to pretend like we are. synchronized (this) { try { wait(50); } catch (InterruptedException e) { } } } } }; /** * Fragment initialization. We way we want to be retained and * start our thread. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Tell the framework to try to keep this fragment around // during a configuration change. setRetainInstance(true); // Start up the worker thread. mThread.start(); } /** * This is called when the Fragment's Activity is ready to go, after * its content view has been installed; it is called both after * the initial fragment creation and after the fragment is re-attached * to a new activity. */ @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Retrieve the progress bar from the target's view hierarchy. mProgressBar = (ProgressBar)getTargetFragment().getView().findViewById( R.id.progress_horizontal); // We are ready for our thread to go. synchronized (mThread) { mReady = true; mThread.notify(); } } /** * This is called when the fragment is going away. It is NOT called * when the fragment is being propagated between activity instances. */ @Override public void onDestroy() { // Make the thread go away. Log.d(TAG, "onDestroy"); synchronized (mThread) { mReady = false; mQuiting = true; mThread.notify(); } super.onDestroy(); } /** * This is called right before the fragment is detached from its * current activity instance. */ @Override public void onDetach() { // This fragment is being detached from its activity. We need // to make sure its thread is not going to touch any activity // state after returning from this function. Log.d(TAG, "onDetach"); synchronized (mThread) { mProgressBar = null; mReady = false; mThread.notify(); } super.onDetach(); } /** * API for our UI to restart the progress thread. */ public void restart() { synchronized (mThread) { mPosition = 0; mThread.notify(); } } } }
Fragment通过实现 onCreateOptionsMenu() 向 Activity 的应用栏添加菜单项。不过,为了使此方法能够收到调用,您必须在 onCreate() 期间调用 setHasOptionsMenu(),以指示片段想要向选项菜单添加菜单项(否则,片段将不会收到对 onCreateOptionsMenu() 的调用)。
锁屏带来的问题
最近我发现了一个我们可能在平常的使用中都没有注意到的问题,锁屏界面对生命周期的影响,很多时候我们的Activity都会直接在onResume或者onPause等地方做一些操作,但是大部分手机都存在锁屏界面,如果我们对锁屏的实现比较熟悉的话都知道其实锁屏界面也是一个Activity。如果我们的Activity处于前台的时候,我们进入了锁屏,那么在开启屏幕的时候(出现锁屏的时候),我们的Activity其实经历了一次onRestart—onStart—onResume—onPause—onStop的生命周期变化,这是因为当我们点开屏幕的时候,首先显示的是我们的Activity,然后系统会在我们的Activity上面打开锁屏应用,这样就导致我们在打开锁屏之前,Activity就经历了一次生命周期的变化,这一问题会留到将来学习KeyGuard的时候再进行深入研究
- Fragment篇——面试必问的Fragment的生命周期
- 面试专题之一Fragment的生命周期
- 面试专题之一Fragment的生命周期
- Android中的Fragment ——03(Fragment的生命周期)
- "Fragment"-Android面试必问"精华技能点"汇总
- 关于Fragment的生命周期
- Fragment的生命周期
- 3.2 Fragment的生命周期
- Fragment的生命周期
- Fragment的生命周期初识
- Android-Fragment的生命周期
- Fragment的生命周期
- Fragment 的生命周期
- Fragment 的生命周期
- Fragment的生命周期
- Fragment的生命周期
- 【Android】Fragment的生命周期
- Fragment 的生命周期
- Leetcode 204shouxi Count Primes
- MVC模式
- 【Leetcode】171. Excel Sheet Column Number,168. Excel Sheet Column Title
- 【error】getHibernateTemplate报错只读
- Mac OS X无法休眠?教你用pmset找出原因。
- Fragment篇——面试必问的Fragment的生命周期
- 卡片式设计_总结及实践记录
- 告别过气的DDOS,浅析各种DDOS手段和防范。
- MacOSX安装和使用mysql
- jqueryui 关于tabs与<base href="<%=basePath%>">冲突的问题
- 需求 有50个人跟随一起,形成震慑力量, 有车,配备武器。
- 【Learning Notes】生成式对抗网络(Generative Adversarial Networks,GAN)
- 程序员40条
- [Audacity][帮助手册][手册内容]认识Audacity