zoukankan      html  css  js  c++  java
  • Android_Fragment的生命周期与返回栈BackStack

    Fragment初探

    为了让界面可以在平板上更好地展示,Android在3.0版本引入了Fragment(碎片)功能,它非常类似于Activity,可以像Activity一样包含布局。Fragment通常是嵌套在Activity中使用的,现在想象这种场景:有两个Fragment,Fragment 1包含了一个ListView,每行显示一本书的标题。Fragment 2包含了TextView和ImageView,来显示书的详细内容和图片。

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:background="#00ff00" >  
      
        <TextView  
            android:layout_width="wrap_content"  
            android:layout_height="wrap_content"  
            android:text="This is fragment 1"  
            android:textColor="#000000"  
            android:textSize="25sp" />  
    </LinearLayout>  

    Fragment1

    public class Fragment1 extends Fragment {  
        @Override  
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
            return inflater.inflate(R.layout.fragment1, container, false);  
        }  
    }  

    主Activity的布局文件,在里面加入两个Fragment的引用,平分屏幕:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent"  
        android:baselineAligned="false" >  
      
        <fragment  
            android:id="@+id/fragment1"  
            android:name="com.example.fragmentdemo.Fragment1"  
            android:layout_width="0dip"  
            android:layout_height="match_parent"  
            android:layout_weight="1" />  
      
        <fragment  
            android:id="@+id/fragment2"  
            android:name="com.example.fragmentdemo.Fragment2"  
            android:layout_width="0dip"  
            android:layout_height="match_parent"  
            android:layout_weight="1" />  
      
    </LinearLayout>  

    Fragment也可以通过在Activity中getFragmentManager()开启事务动态添加和修改

    下面代码为根据屏幕分辨率使用不同Fragment的示例代码

    public class MainActivity extends Activity {  
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.activity_main);  
            Display display = getWindowManager().getDefaultDisplay();  
            if (display.getWidth() > display.getHeight()) {  
                Fragment1 fragment1 = new Fragment1();  
                getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment1).commit();  
            } else {  
                Fragment2 fragment2 = new Fragment2();  
                getFragmentManager().beginTransaction().replace(R.id.main_layout, fragment2).commit();  
            }  
        }  
    }  

    一、Fragment的生命周期初探

    因为Fragment必须嵌入在Acitivity中使用,所以Fragment的生命周期和它所在的Activity是密切相关的。

    如果Activity是暂停状态,其中所有的Fragment都是暂停状态;如果Activity是stopped状态,这个Activity中所有的Fragment都不能被启动;如果Activity被销毁,那么它其中的所有Fragment都会被销毁。

    但是,当Activity在活动状态,可以独立控制Fragment的状态,比如加上或者移除Fragment。

    当这样进行fragment transaction(转换)的时候,可以把fragment放入Activity的back stack中,这样用户就可以进行返回操作。

    使用Fragment时,需要继承Fragment或者Fragment的子类(DialogFragment, ListFragment, PreferenceFragment, WebViewFragment),所以Fragment的代码看起来和Activity的类似。

    每当创建一个Fragment时,首先添加以下三个回调方法:

    • onCreate():系统在创建Fragment的时候调用这个方法,这里应该初始化相关的组件,一些即便是被暂停或者被停止时依然需要保留的东西。
    • onCreateView():当第一次绘制Fragment的UI时系统调用这个方法,该方法将返回一个View,如果Fragment不提供 UI也可以返回null。注意,如果继承自ListFragment,onCreateView()默认的实现会返回一个ListView,所以不用自己 实现。
    • onPause():当用户离开Fragment时第一个调用这个方法,需要提交一些变化,因为用户很可能不再返回来。

    将Fragment加载到Activity当中有两种方式:

    • 方式一:添加Fragment到Activity的布局文件当中
    • 方式二:在Activity的代码中动态添加Fragment(荐)

    第一种方式虽然简单但灵活性不够。添加Fragment到Activity的布局文件当中,就等同于将Fragment及其视图与activity的视图绑定在一起,且在activity的生命周期过程中,无法切换fragment视图。

    第二种方式比较复杂,但也是唯一一种可以在运行时控制fragment的方式(加载、移除、替换)。

    二、Fragment与Activity的生命周期对比

    fragment生命周期示例

    初次加载:(分成两部分来看)

    点击一下home键(或接入电话),打印日志如下:

    重新进入进入程序(或电话结束),打印日志如下:

    点击back键退出程序,打印日志如下:

    通过上面的日志,我们能够看出,Fragment和Activity的生命周期太相似了。只是有几个Activity中没有的新方法,需要重点介绍一下:

    • onAttach方法:Fragment和Activity建立关联的时候调用(获得activity的传递的值)
    • onCreateView方法:为Fragment创建视图(加载布局)时调用(给当前的fragment绘制UI布局,可以使用线程更新UI)
    • onActivityCreated方法:当Activity中的onCreate方法执行完后调用(表示activity执行oncreate方法完成了的时候会调用此方法)
    • onDestroyView方法:Fragment中的布局被移除时调用(表示fragment销毁相关联的UI布局)
    • onDetach方法:Fragment和Activity解除关联的时候调用(脱离activity)

    三、Fragment返回栈的管理

    将Fragment添加到返回栈中:

    假设现在我们有两个Fragment:Fragment01和Fragment02,我们现在从Fragment01的界面跳到 Fragment02,然后按Back键,发现程序是直接退出了,而不是返回到Fragment01。如果现在想实现以下功能:从Fragment01的 界面跳到Fragment02,然后按Back键,会返回到Fragment01。这个功能该怎么实现呢?这其实就利用到了返回栈的知识。

    其实很简单,FragmentTransaction中提供了一个addToBackStack()方法,可以将一个事务添加到返回栈中。

    我们先回顾一下之前动态加载Fragment的代码,然后在此基础之上,增加一行代码就可以将Fragment添加到返回栈中:(即第07行代码)

    //步骤一:添加一个FragmentTransaction的实例
    FragmentTransaction transaction = getFragmentManager().beginTransaction();
    //步骤二:用add()方法加上Fragment的对象
    RightFragment rightFragment = new RightFragment();
    transaction.add(R.id.right, rightFragment);
    transaction.addToBackStack(null);
    //步骤三:调用commit()方法使得FragmentTransaction实例的改变生效 transaction.commit();

    我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接受一个名字用于描述返回栈的状态,一般传入null即可。

    例子

    @Override
         public void onClick(View v) {
             // TODO Auto-generated method stub
     transaction = manager.beginTransaction(); 47         switch (v.getId()) {
             case R.id.button1:
                 Fragment01 fragment01 = new Fragment01();
                 transaction.replace(R.id.right, fragment01, "fragment01");
                 transaction.addToBackStack("fragment01");// 添加到Activity管理的回退栈中。
                 break;
     
             case R.id.button2:
                 Fragment02 fragment02 = new Fragment02();
                 transaction.replace(R.id.right, fragment02, "fragment02");
                 transaction.addToBackStack("fragment02");// 添加到Activity管理的回退栈中。
                 break;
     
             case R.id.button3:
                 Fragment03 fragment03 = new Fragment03();
                 transaction.replace(R.id.right, fragment03, "fragment03");
                 transaction.addToBackStack("fragment03");// 添加到Activity管理的回退栈中。
                 break;
    
             }
      transaction.commit();      
         }

    运行程序后,界面如下,没有任何fragment被加载:

    点击按钮加载fragment01:

    点击按钮加载fragment02(此时fragment01被替换,并被压到了栈当中):

    注:如果fragment01在替换的时候没有被压到栈中,那就会被销毁,在执行完onDestroyView()方法后,会继续执行onDestroy()和onDetach()方法。

    按Back键,fragment01重新返回到屏幕:(fragment02被销毁)

    再按Back键,fragment01被销毁:

    注:Fragment的返回栈由Activity管理;而Activity的返回栈由系统管理。

  • 相关阅读:
    C语言实现链表
    获取两个数之间的随机数-java
    C#继承机制 多级继承
    C#继承机制 访问与隐藏基类成员
    C#继承机制 C#中的继承符合下列规则
    C#装箱与拆箱的研究
    C#箴言之用属性来访问类的私有成员
    C# 创建和初始化集合对象
    C# 常用函数和方法集汇总
    C# 多态与new关键字
  • 原文地址:https://www.cnblogs.com/updateofsimon/p/4479743.html
Copyright © 2011-2022 走看看