zoukankan      html  css  js  c++  java
  • 【幻化万千戏红尘】qianfeng-Android-Day18_Fragment

    Fragment

    一、Fragment的概念和用法:

    (一)、概念:

            Fragment是在Android 3.0 (API level 11)开始引入新的API技术。

            为了提高代码重用性和改善用户体验,我们将Activity中的UI组件进行分组和模块化管理。这些分组后的UI组件就是Fragment

            一个Activity页面中可以包含多个Fragment模块,而同一个Fragment模块也可以被多个Activity使用。每个Fragment有自己的布局,有自己的生命周期。虽然Fragment拥有自己的生命周期,但因为Fragment必须被嵌入到Activity中使用,因此Fragment的生命周期是受其Activity宿主的生命周期所控制的。当Activity暂停时,该Activtiy内的所有Fragment都会暂停;当Activity被销毁时,该Activity内的所有Fragment都会被销毁。

    (二)、Fragment为什么能改善用户体验,另外Fragment能用于平板电脑,那么普通的手机屏幕适用吗?

    答案是肯定的。Fragment本身是可复用的组件。是否在一个Activity页面中放置多个Fragment取决了屏幕的大小,如果屏幕大小不够,那么就可以在Activity A中只包含Fragment A,在Activity B中只包含Fragment B,点击A中的item跳转到B就可以。

    (三)、Fragment要点:【重点

        1Fragment作为Activity界面的一部分组成出现;

        2、可以在一个Activity中同时出现多个Fragment,并且,一个Fragment亦可在多个Activity中使用;

        3、在Activity运行过程中,可以添加移除替换、隐藏、显示Fragmentadd()remove()replace()hide()show());

        4Fragment可以响应自己的输入事件,并且有自己的生命周期,当然,它们的生命周期直接受其所属的宿主Activity的生命周期控制。

        5FragmenetTransaction的方法:

    • 使用replace()替换后会将之前的fragmentviewviewtree中删除
    • 使用hide()方法只是隐藏了fragmentview并没有将viewviewtree中删除,随后可用show()方法将view设置为显示
    • android.app.Fragment 主要用于定义Fragment 
    • android.app.FragmentManager 主要用于在Activity中操作Fragment 
    • android.app.FragmentTransaction  

    (四)、Fragment家族常用的API

    1、Fragment常用的三个类:

    2、获取FragmentManage的方式:

    getFragmentManager() // v4中,getSupportFragmentManager

    3、主要的操作都是FragmentTransaction的方法

        FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

    • transaction.add()      Activity中添加一个Fragment 
    • transaction.remove()    Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。
    • transaction.replace()    使用另一个Fragment替换当前的,实际上就是remove()+add()的合体 
    • transaction.hide()    隐藏当前的Fragment,仅仅是设为不可见,并不会销毁 
    • transaction.show()   显示之前隐藏的Fragment 
    • transatcion.commit()    提交一个事务
    • fragment.isAdded()  判断一个Fragment是否已经被添加到事务中 

    二、Fragment生命周期:

    (一)、Fragment基本状态:

        1、活动状态:Resumed   当前Fragment位于前台,用户可见,可以获得焦点;

        2、暂停状态:  Paused   另一个Activity处于前台并拥有焦点, 但是该Fragment所在的Activity仍然可见(前台Activity局部透明或者没有覆盖整个屏幕),不过不能获得焦点;

        3、停止状态:Stopped

    要么是宿主Activity已经被停止, 要么是FragmentActivity被移除但被添加到回退栈中;停止状态的Fragment仍然活着(所有状态和成员信息被系统保持着)。 然而, 它对用户不再可见, 并且如果Activity被销毁,它也会被销毁;

        4、销毁状态:Destroyed  只能等待被回收。

    (二)、Fragment生命周期:【重点

    方法

    描述

    onAttach(Activity)

    当前Fragment与Activity关联,调用!

    onCreate()

    完成fragment的初始化创建

    onCreateView()

    创建并返回与当前fragment相关联的层次视图view

    onActivityCreated()

    主activity的onCreate()执行完后,该方法才执行

    onStart()

    fragment可见,当主activity处于started状态后执行

    onResume()

    fragment能与用户交互,当主activity处于resumed状态后执行

    onPause()

    fragment不在与用户交互,可能在主activity将要处于paused前执行,可能该fragment被修改

    onStop()

    fragment不在可见,可能在主activity将要处于stopped前执行,可能该fragment被修改

    onDestroyView()

    允许该fragment清理视图相关资源

    onDestroy()

    清理掉视图state信息

    onDetach()

    该fragment不在于activity关联

    1onAttach(): 当该Fragment被添加到Activity时被回调。该方法只会被调用一次;

    2onCreate():  当创建Fragment时被回调。该方法只会被调用一次;

    3onCreateView():每次创建、绘制该FragmentView组件时回调该方法,Fragment将会显示该方法返回的View 组件;

    4onActivityCreated(): Fragment的宿主Activity被启动完成后回调该方法;

    5onStart(): 启动Fragment时被回调;

    6onResume():  onStart()方法后一定会回调onResume()方法;

    7onPause(): 暂停Fragment时被回调;

    8onStop(): 停止Fragment时被回调;

    9onDestroyView():  销毁该Fragment所包含的View组件时调用;

    10onDestroy():  销毁Fragment时被回调。该方法只会被调用一次;

    11onDetach():  FragmentActivity中删除、替换完成时调用该方法。onDestroy()方法后一定会回调onDetach()方法。该方法只会被调用一次。

    【备注:】其中大多数程序必须实现Fragment的三个回调方法分别为: 

    onCreate :系统创建Fragments 时调用,可做执行初始化工作或者当程序被暂停或停止时用来恢复状态,跟Activity 中的onCreate相当。  

    onCreateView :用于首次绘制用户界面的回调方法,必须返回要创建的Fragment 视图UI。假如你不希望提供Fragment用户界面则可以返回NULL 

    onPause  当用户离开这个Fragment的时候调用,这时你要提交任何应该持久的变化,因为用户可能不会回来。

    (三)、示例代码:

    1Fragment的布局文件:

    <fragment
        android:id="@+id/fg"
        android:name="org.mobiletrain.fragment1.MyFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:layout="@layout/myfragment_layout"/>

    3Fragment文件中的java代码:

    public class MyFragment extends Fragment implements View.OnClickListener {

        private static final String TAG = "fragment";

        //当Fragment和Activity产生关联的时候调用
        //参数activity表示宿主Activity
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            Log.d(TAG, "onAttach() returned: ");
        }

        //创建fragment时调用该方法
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate() returned: ");
        }

        //返回Fragment的布局
        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            Log.d(TAG, "onCreateView() returned: ");
            View view = inflater.inflate(R.layout.myfragment_layout, null);
            Button button = (Button) view.findViewById(R.id.go);
            button.setOnClickListener(this);
            return view;
        }

        //当宿主Activity创建完成时调用
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            Log.d(TAG, "onActivityCreated() returned: ");
        }

        @Override
        public void onStart() {
            super.onStart();
            Log.d(TAG, "onStart() returned: ");
        }

        @Override
        public void onResume() {
            super.onResume();
            Log.d(TAG, "onResume() returned: ");
        }

        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, "onPause() returned: ");
        }

        @Override
        public void onStop() {
            super.onStop();
            Log.d(TAG, "onStop() returned: ");
        }

        //销毁Fragment的视图
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            Log.d(TAG, "onDestroyView() returned: ");
        }

        //销毁Fragment
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG, "onDestroy() returned: ");
        }

        //Fragment和Activity解除关系时调用
        @Override
        public void onDetach() {
            super.onDetach();
            Log.d(TAG, "onDetach() returned: ");
        }

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.go:
                    startActivity(new Intent(getActivity(), BActivity.class));
                    break;
            }
        }
    }

    (四)、运行结果观察:

    1、第一次加载Fragment

    onAttach()àonCreate()àonCreateView()àonActivityCreated()àonStart()àonResume()

    2、在MainActivity中,点击返回键退出程序:

    onPause()àonStopàonDestoryView()àonDestoty()àonDetach()

    3、在MainActivity中,点击“HOME退出程序:

    onPause()àonStop()

    【备注:】请注意第二种和第三种情况的区别。如果点HOME键退出,则少调用了onDestroyView()onDestroy()onDetach()三个回调方法。

    4、点击下一页,进入NextActivity页面:

    onPause()àonStop()

    (五)、跟Fragment生命周期相关的其他方法:

    1onInflate():在onCreate()方法之前调用,这时窗体上的控件都没有被创建,所以不能通过getActivity().findViewById(),因为此时getActivity()返回null

    2onViewCreated():在onCreateView()方法后会立刻调用onViewCreated()方法。通常在该方法中完成创建Fragment的最后工作

    (六)、如果Activity生命周期和Fragment生命周期的Log都开启,那么依次会如何输出信息呢?

    1、第一次加载MainActivity页面:

    A-onCreate()àF-onAttach()àF-onCreate()àF-onCreateViewàF-onActivityCreated()àA-onStart()àF-onStart()àA-onResume()àF-onResume()

    2、在MainActivity页面中,点击返回键退出程序:

    F-onPause()àA-onPause()àF-onStop()àA-onStop()àF-onDestoryViewàF-onDestory()àonDetach()àA-onDestory

       3、在MainActivity中,点击“HOME退出程序:

    F-onPause()àA-onPause()àF-onStop()àA-onStop()

    【备注:】请同学们注意观察Activity回调方法和Fragment回调方法执行的顺序。请设想各种操作步骤,写出生命周期回调方法执行的顺序。

    特别强调:】

    ActivityonCreate()方法中,如果将Log的位置放在setContentView(R.layout.activity_main)之前,那么ActivityonCreate()方法就会在最先执行,如果将日志写在setContentView(R.layout.activity_main)之后,那么ActivityonCreate()方法就会在FragmentonViewCreated()之后执行。

    三、创建Fragment:

    (一)、创建Fragment的步骤:【只需要两步

    1、创建一个Fragment,必须继承Fragment 这个基类或其子类;

    2、实现回调方法:

            Fragment类的代码看起来很像 Activity 。它包含了和activity类似的回调方法, 例如onCreate()、 onStart()、onPause()以及 onStop()。事实上,,如果你准备将一个现成的Android应用转换到使用Fragment,可能只需要将代码从你的Activity的回调方法中分别移动到你的Fragment的回调方法即可。

            通常,应当至少实现如下的生命周期方法:

    onCreate()

    当创建fragment时, 系统调用该方法. 

    在实现代码中,应当初始化想要在fragment中保持的必要组件, 当fragment被暂停或者停止后可以恢复.

    onCreateView()

    fragment第一次绘制它的用户界面的时候, 系统会调用此方法. 为了绘制fragment的UI,此方法必须返回一个View, 这个view是你的fragment布局的根view. 如果fragment不提供UI, 可以返回null.

    onPause()

    用户将要离开fragment时,系统调用这个方法作为第一个指示(然而它不总是意味着fragment将被销毁.) 。在当前用户会话结束之前,通常应当在这里提交任何应该持久化的变化(因为用户有可能不会返回).

        【备注:】对于大部分Fragment而言,通常实现三个回调方法即可。但是实际开发中可以根据需要重写Fragment生命周期中的任意回调方法。    

    四、动态创建Fragment

    (一)、概念:

    如果将Fragment写在布局文件中,那么就是静态创建fragment;如果没有在布局文件中写<fragment>标签,而是在java文件中通过实例化Fragment创建Fragment的方式就是动态创建Fragment。

    (二)、动态创建Fragment的步骤:

    1、步骤:

    (1)获得一个Fragment管理器

    FragmentManager manager = getFragmentManager();

    (2)开启一个事务

    FragmentTransaction transaction = manager.beginTransaction();

    (3)添加或者替换Fragment

    //用Fragment替换Linearlayout(remove和add结合体)
    //        transaction.replace(R.id.ll, new MyFragment());
            //添加一个Fragment
    //        transaction.add(R.id.ll, new MyFragment());

    2、Activity布局文件代码:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="org.mobiletrain.fragment1.MainActivity">

        <LinearLayout
            android:id="@+id/ll"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"></LinearLayout>
    </RelativeLayout>

    五、Fragment之间的数据交互:

    (一)、FragmentFragment传递数据:Arguments

    1、做法:

            可以通过Fragment.setArguments()方法向Fragment传递数据,并且通过getArguments()方法获取传递的数据。

    2、核心代码:

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            //第一种通信方式
            String s = list.get(position);
            Fragment fragment = new RightFragment();
            Bundle args = new Bundle();
            args.putString("value", s);
            //通过setArguments方式传递参数
            fragment.setArguments(args);
            FragmentManager manager = getFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.replace(R.id.ll, fragment);
            transaction.commit();
        }
    });

    (二)、Fragment回调机制

    1、原则:

    Fragment类要尽量保证其独立性Fragment类中不应该有访问其他Fragment和Activity中资源的代码,否则这个Fragment就不能在不改动代码的情况下用在其他地方。

    如何让多个Fragment之间可以独立多次使用,而不是紧密地绑定到一起?通常的做法就是在Fragment类中编写一个接口,然后在该Fragment的宿主窗口类中实现该接口。这样Fragment与其宿主就实现了信息交互。

    2、Fragment接口回调的步骤:(五步曲)

    1.Fragment文件中定义接口:MyItemClickInterface,定义抽象方法public void updateText(String fileName);

    2.Fragment文件中定义属性:private MyItemClickInterface myactivity;

    3.Fragment文件中的onAttach()方法中执行:if (activity instanceof MyItemClickInterface) {

                myactivity = (MyItemClickInterface) activity;

            }

    4.Fragment文件中,给某个控件增加监听器,在监听器中执行://5.调用接口
    myactivity.updateText(list.get(position));

    5.MainActivity实现MyItemClickInterface,重写updateText(String fileName)方法。参数就是Fragment传递的数据信息,在该方法中执行希望的逻辑操作。

    六、FragmentManager与Fragment事务:  【重要】

    (一)、FragmentManager与FragmentTransaction示例代码:

    Fragment的布局文件:

    // 构建Bundle对象,将文章title放在其中。

    Bundle bundle = new Bundle();

    bundle.putString("fileName", fileName);

    // 构建文章内容的Fragment

    RightFragment fragment = new RightFragment();

    // 通过fragment对象的setArguments(bundle)方法将数据传输给其他Fragment。

    fragment.setArguments(bundle);

    // 通过getFragmentManager()方法构建FragmentManager对象

    FragmentManager fragManager = getFragmentManager();

    // 通过FragmentManager对象的beginTransaction()方法构建FragmentTransaction对象

    FragmentTransaction trans = fragManager.beginTransaction();

    // 将主页面布局文件中的ViewGroup容器替换成文章内容Fragment

    trans.replace(R.id.fragment_content, fragment);

    // 提交事务

    trans.commit();

    (二)、 FragmentTransaction中的replace方法与add、hide、show方法的区别:【重要】

    1. * 使用replace()方法实现。 每次replace都会将当前的碎片进行销毁,新创建一个碎片将原有的进行替换
    2. * 使用add()、hide()、show()方法实现。被加载出来的碎片在导航切换过程中不会被销毁,只是在隐藏和显示两个状态切换而已。
    3. * 因为切换过的碎片不被销毁,自然会有内存占用上的开销,但是因为不用重新加载碎片而在性能上是优于replace的。
  • 相关阅读:
    基础数据类型补充、集合、深浅拷贝
    python中(id,is,==,)小数据池,代码块
    字典:python的基础数据类型
    五四青年节后记
    test
    agl---atumotive grade linux开篇
    传感器
    金字塔原理
    写在2017年底
    C# 输出16进值
  • 原文地址:https://www.cnblogs.com/weigongcheng/p/5886448.html
Copyright © 2011-2022 走看看