zoukankan      html  css  js  c++  java
  • Android学习笔记(一): Fragment(一) 基本概念和生命周期

    为何引入Fragment

    我们之前的Activity都是都是全屏处理较为简单的单一事务功能,适合于屏幕尺寸较小的智能手机,但是对于平板,有更大的显示空间,运行用户在上面处理更多的功能,例如屏幕左边是email列表,右边的某email的内容。于是在Android 3.0引入了fragment。Fragment不仅可用于平板,同样也可用于手机尺寸.

    大小屏幕的适配

    某种意义上Fragment是屏幕中的一个子activity,但是在一个屏幕显示多个activity会造成概念和逻辑的混乱,所以引入fragment的概念,可以理解为屏幕中的一块UI,可作为activity的一部分。Fragment是view的容器,加载layout,处理一小部分屏幕,它是activity的一部分。Fragment提供的UI和代码的重用,例如,在大屏幕设备中,显示左右两个fragment或者上下两个fragment(具体看orientation),在小屏幕设备中则显示其中一个fragment。

    使用fragment,将很容易处理这种情况,activity只需要对fragment进行布局,具体的view的摆放和操作,由fragment进行处理

    横屏、竖屏切换

    当屏幕进行横屏/竖屏的切换(模拟器转向可以简单按数字小键盘的“7”),activity会退出,从代码中看调用了onDestroy(),重新加载activity(调用了onCreate()),我们需要对原有状态保存,以便切换屏幕后,用户能继续操作,而不是重头开始。保存数据或状态会比较麻烦,可以用fragment来解决。

    返回键

    按返回键,activity同样也会调用onDestroy()退出。如果在应用中,再次进入该activity,有时也会希望在上次基础上继续执行,同样也存在状态保持的问题。fragment中,按返回键,根据fragment stack进行回退,仍然留在当前的activity中。

    activity切换屏幕或者退出,是重头再来,对原有数据的保存会比较麻烦.

    fragment,如该按返回键,会根据fragment stack进行回退,但仍然留在当前的activity中.

    什么是Fragment

    Activity是Context的继承,而fragment是Object的继承,在android.app包中。fragment可具有层次结构的view(来自xml或者代码)。Fragment有一个bundle可以存贮数据,和activity类似,在创建时进行初始化调用,此外还有一个bundle用于保存现有状态,在onCreate(),onInflate(),onCreateView() 和onActivityCreated()都指向该对象。

    一个activity可以显示多个fragment,如果fragment A被fragment B替代,则fragment A会被放入back stack中,用户按返回键时,可以重新显示fragment A。

    一个fragment具有一个tag和一个ID,可用于索引

    fragment的生命周期如下。这个图先放在这里,以后结合小例子理解。


    小例子:

    小例子运行效果

    这是一个书名和书简介的例子。运行如下图。Activity由左右两个Fragment组成,左边显示书名列表,右边显示书的简介。用户点击左边的书名,右边fragment则自动显示该书的简介。

    其实就两个Fragment在一个Acitivity中.

    Acitivity的布局可以为: 在布局中就有  Fragment 和 FrameLayout, Fragment对应的路径是Fragment类,所以说Activity只需要设置布局就行了.

    <?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        android:orientation="horizontal" > 
        <!-- 设置左边Fragment的id,并直接通过class属性给出该fragement对应的类为TitleFragment,需要注意fragment并不是view,不支持里面子tag,即不支持<fragment …. ><…></fragment>的格式  -->
        <fragment class="com.wei.flowingflying.pro.ProFragment.TitleFragment"
            android:id="@+id/titles" 
            android:layout_weight="1" 
            android:layout_width="0px" 
            android:layout_height="match_parent" />  
         <!-- 注意:这是FrameLayout,不是fragment,是view,右边fragment的呈现有左边fragment的操作决定,不指定对应的类,可以由不同的类来具体实现UI -->
          <FrameLayout android:id="@+id/details" 
                android:layout_weight="2" 
                android:layout_width="0px" 
                android:layout_height="match_parent" /> 
    </LinearLayout>

    实现Fragment指定调用类TitleFragment

    Fragment可有一个view hierarchy(视图对象),以之与用户互动。这个view层级可以根据XML布局文件被创建(inflated)或通过代码创建。view层级需要与activity关联,才能被用户看见。Fragment的最初的两个生命周期为onInflate和onAttach

    1.onInflate() 被创建

    首先调用:在Activity调用setContentView()时,xml中有<fragment>时被调用。bundle存贮的是fragment的状态,并非初始化的值。一般而言,此时太早,还没有和activity关联,一般很少需要在此进行处理,除非我们需要处理fragment的属性或参数。在API的reference中,Fragment的主要lifecycle甚至没有将onInflate()列入,因此在实际编程中,会较少用到。

    2.onAttach() :

    fragment 与 activity 关联后调用// 在其他方法中实现需要获取activity对象,getActivity()

      @Override //【2】在fragment与activity关联后调用onAttach()。由于右边fragment的具体实现在activity的showDetails()中实现,需要获取activity的对象。 当然也可以直接用getActivity()获取。
        public void onAttach(Activity activity) {  
            showInfo("onAttach() is called. activity is " + activity); 
            showInfo("   getActivity() : " + getActivity());
            super.onAttach(activity);
            myActivity = (FragmentBasicTest)activity; 
        }  

    调用:activity调用setContentView时,先调用Flagment中的onflate(),然后调用onAttach()。在onInfalte()中可以读取到我们setContentView里面的布局xml文件                

            <fragment… >设置的属性。如果布局文件中<fragment …>中并没有指定class属性,而是在代码中实现,故没有onInflate()状态。

    与activity的关联:看到onInfalte()和onAttach()都可以获得activity对象,但是如果采用getActivity()来获取,则发现onInfalte()的阶段对处理UI太早,都不能关联到activity。

    参数:在整个生命周期,可以通过getArguments()来获取参数,但是不能在与activity关联后进行setArgments(),只能在初始化极早的阶段,例如构造函数和onInflate()。

    3.onCreate()和onCreateView()

    @Override 
    //【3】在创建fragment中进行初始化时调用。注意此处的bundle参数,是存储fragment的状态。[如果我们要为fragment启动一个后台线程,可以考虑将代码放于此处。??how] public void onCreate(Bundle savedInstanceState) { showInfo("onCreate() is called. "); super.onCreate(savedInstanceState); } @Override //【4】创建fragment,并返回fragment的view层次结构,用于对UI的设计。本例继承了ListFragment实现,由其生成ListView,它的资源ID是android.R.id.list1,或者可以通过getListView()来获取。我们在此不需要在进行特别的处理,仅用于跟踪生命周期。 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { showInfo("onCreateView() is called. "); return super.onCreateView(inflater, container, savedInstanceState); }

    onCreate()和onCreateView()都是在activity调用setContentView()时被调用。也就是activity上未完成onCreate(),因此不应该在此加入与activity的view相关的代码。而后面的生命周期这是在activity完成onCreate()之后调用的。

    onCreate(): 用于初始化 Fragment (有Bundle可以传递参数)

    onCreateView():(创建Fragment ,并返回fragment的view层次结构,用于UI设计)


    onActivityCreated()

    onActivityCreated顾名思义,是在activity完成onCreate()后被调用。我们可以在此处理activity的其他UI操作,而其他的fragment已经与activity关联,我们可以进行相互间处理。这也是用户看到UI界面之前的最后一个状态,对于从saved状态中重新创建activity及fragment来讲是重要状态。

    回想一下,在ListActivity中是在setContentView()后面进行Adapter的设置,因为setContentView已经提供了view层级,因此在fragment中具体设置list也放在fragment的onCreateView()之后的生命周期onActivityCreated()中执行。

       @Override //【5】onActivityCreated()在activity完成onCreate()后执行,在此可以加入UI设计(onCreateView())之后,UI被用户看到之前的代码。 
        public void onActivityCreated(Bundle savedInstanceState) {  
            showInfo("onActivityCreated() is called.");
            super.onActivityCreated(savedInstanceState); 
           // 1)通过Adapter进行view和data的关联   
            setListAdapter(new ArrayAdapter<String>(getActivity(),   //注意:在ListFragment中不要直接和ListView(通过id或者getListView()获取)关联,而要用setListAdapter()
                    android.R.layout.simple_list_item_1, 
                    BooksInfo.TITLES)); 
            ListView lv = getListView(); 
            lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
            lv.setSelection(mCurCheckPosition); 
            //2)根据书名设置右边framgent UI。 
            myActivity.showDetails(mCurCheckPosition); 
        }
    

      


    onStart()、onResume()、onPause()和onStop()

    这几个状态和activty的相应状体相似,对应为可视,可互动,不可互动和不可视。和activity的生命周期图相对比,从不可视的后台回复到可视的前台的过程是onStop()—>onRestart()—>onStart()。而fragment为onStop()—>onStart()。


    onDestroyView()、onDestroy和onDetach()

    当fragment允许与view相关的资源释放时调用onDestroyView(),清空通过onCreateView()所返回的view。接着,onDestroy()进行最后fragment状态的清空。最后调用onDetach(),删除与activity的关联()。

  • 相关阅读:
    request.getParameter() 和request.getAttribute() 区别
    Java中this和super的用法总结
    jQuery实现列表框双向选择操作
    Eclipse中.setting目录下文件介绍
    通过Ajax方式上传文件,使用FormData进行Ajax请求
    ASP.NET程序中常用的三十三种代码
    计算地球上两个坐标点(经度,纬度)之间距离sql函数
    动态调用WebService(C#) (非常实用)
    带SoapHeader验证的WebServices
    GridView内容详解(转载)
  • 原文地址:https://www.cnblogs.com/zzblee/p/4372286.html
Copyright © 2011-2022 走看看