Fragment详解(1)

嗨!又和大家见面了(每次都是这个开场白有点瓜,,下次换一个-。+),之前我们介绍过Activity,他在UI显示和用户交互的过程中起着重要的作用,但是除了Activity之外,我们还有一个类,也负责同样的功能,他就是Fragment,相信大家也用到过,今天我们详细的讲解一下这个Fragment类。

一、产生意义

1.为了适配不同尺寸的手机以及平板和手机的适应。

    这个应该很好理解:我们以前在做应用开发时候,首先需要先针对手机开发一套App,然后在针对平板的尺寸开发另一套App(布局修改),但是这样很捞啊,不但麻烦,而且也做了很多无用功,而Fragment的出现完美的解决了这个问题:Fragment可以被放在Activity的布局中,使我们的视图是由一块块Fragment组成的,这样我们可以根据尺寸的不同进行Fragment的调整。从而解决上述问题。

2.减轻Activity负担。

    Fragment也是有自己的生命周期的,而且由于跟Activity绑定,有些生命周期是和Activity同步的(onStart、onResume之类),所以我们的一些在Activity进行用户操作的逻辑代码,可以写到Fragment中,减少了Activity的代码量。

二、生命周期

直接上图可能更明确些:

       

这里有两张图(反正都不是我画的-。+,但是这两张图是真的棒,所以我粘贴过来了):

    第一张是Fragment相对比较完整的生命周期,我们注意到当Fragment即将失去焦点时(绿色方框下面),他有两种情况,一种是将Fragment添加到退回栈(back Stack),还有一种情况是没有添加。他们在进行到onDestroyView方法之后生命周期是不相同的,这里只是稍微提一下,今天我们讲的不涉及到退回栈。

    第二张图是Activity生命周期方法和Fragment生命周期方法的联系,我们注意到中间的几个方法Activity和Fragment是同步的。

接下来简单地描述一下相关生命周期方法:

  • onAttach:让Fragment和Activity关联,此时关联的Activity已经被传进来,可以通过getActivity获取Activity实例(但是有些时候使用需要强转)。
  • onCreate:在Fragment实例被创建时候调用。
  • onCreateView:Fragment视图创建过程。
  • onViewCreated:当onCreateView方法返回后立即调用,此时Fragment的层次结构还没有添加到父节点上(这个方法一般没有被提到,但是我想在这里提一下。)
  • onActivityCreated:当Activity创建完成,而且该Fragment的层次结构也被实例化,调用。
  • onStart:在Fragment可见的时候调用,通常与Activity的生命周期相关联。
  • onResume:当Fragment可见而且可获取焦点时调用,通常与Activity的生命周期相关联。
  • onPause:当Fragment失去焦点时调用,通常与Activity的生命周期相关联。
  • onStop:当Fragment不可见时候调用,通常与Activity的生命周期相关联。
  • onDestroyView:当Fragment与其先前创建的视图分离时调用。
  • onDestroy:当Fragment实例被销毁时调用。‘
  • onDetach:Fragment解除关联。

浓缩了半天,可是写完发现话还是很多,简单总结一下:

我们把这些方法分成三大类:

  1. 创建
  2. 与Activity同步的方法
  3. 销毁

其中创建的相关方法为:onAttach,onCreate,onCreateView,onViewCreated,onActivityCreated。这里面说的创建是关于Fragment视图和实例的创建过程以及Fragment实例与Activity绑定的过程。

与Activity同步的方法就很简答了,他们与Activity的对应生命周期方法是同步执行的:onStart,onResume,onPause,onStop。

销毁的相关方法为:onDestroyView,onDestroy,onDetach。销毁是对Fragment实例、视图的销毁,以及Fragment与Activity取消关联。

以上是对生命周期的讲解,我们可以告一段落了。

三、Fragment使用

Fragment分为静态使用和动态使用的过程:

静态使用:

关于静态使用我个人感觉用处不大,而且没什么好讲的,因为使用的时候还是动态使用的比较多,我们就简单看一下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/f1"
        android:name="zy.pers.fragmenttext.OneFragment"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        >
        
    </fragment>

    <fragment
        android:id="@+id/f2"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:name="zy.pers.fragmenttext.TwoFragment"/>

</LinearLayout>

这是我们MainActivity的布局文件,很简单,只是往里面放入了两个碎片,

然后我们还需要这两个碎片:

public class OneFragment extends Fragment {
    private static final String TAG = "OneFragment";

    ......

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        Log.e(TAG, "onCreateView: ");
        View view = inflater.inflate(R.layout.one_fragment, container, false);
        return view;

    }

    ......
}

这是OneFragment的类。

这里我们只是需要创建出来显示,并没有实现哪些功能,所以我们只重写了onCreateView方法,在里面调用了inflate方法加载了布局。

所以我们还需要一个布局文件:

<?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:background="@color/colorPrimary">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="OneFragment"
        android:textAllCaps="false"
        android:textColor="@color/whilte"
        android:textSize="28sp"
        android:gravity="center"/>
</LinearLayout>

这是OneFragment的布局文件,上了个颜色,放了一个TextView。

TwoFragment同一。

现在我们启动程序看一下效果:


看着很蠢。。。。因为他就是这么简单。我们直接看动态添加:

动态使用:

我们刚才静态使用是被锁死的布局,也就是说他无法改变,而动态布局是我们动态添加Fragment,这里要用到一个熟悉的布局——FrameLayout。我们直接看代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity"
    >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <Button
            android:id="@+id/fra1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="addone"

            android:textAllCaps="false" />

        <Button
            android:id="@+id/fra2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="visible"
            android:text="addtwo"
            android:textAllCaps="false" />

     
    </LinearLayout>


    <FrameLayout
        android:id="@+id/frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

在布局中添加了一个线性布局和一个帧布局。线性布局中放置了两个按钮,一个用来添加OneFragment,一个用来添加TwoFragment。

    findViewById(R.id.fra1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager manager = getSupportFragmentManager();
                FragmentTransaction transaction = manager.beginTransaction();
                transaction.add(R.id.frame, oneFragment).commit();
            }
        });
        findViewById(R.id.fra2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager manager = getSupportFragmentManager();
                FragmentTransaction transaction = manager.beginTransaction();
                transaction.add(R.id.frame, twoFragment).commit();
            }
        });

这是我们写在MainActivity中用来添加Fragment的代码(这几个方法下面会详细介绍的)。

效果:    

上面的代码只是展示一下Fragment的使用,里面提到了两个类:FragmentManger和FragmentTransaction:

  • FragmentManager类负责管理Fragment。通过getFragmentManager和getSupportFragmentManager方法获取。
  • FragmentTransaction类主要负责对Fragment的添加,移除,替换,显示,隐藏等操作。

我们下面具体介绍一下FragmentTransaction类(FragmentManager类详细在下一篇中介绍。):

四、FragmentTransaction相关方法。

我们提到了FragmentTransaction的作用,上面也用到了add这个方法,那我们先从add方法开始讲起吧:

以下全部都是文档解释翻译的(自己翻译的,精神可嘉-。+)

  • add将Fragment添加到Activity状态中,这个Fragment可以选择创建自己的view,添加到Activity的容器视图中(如果onCreateView返回非空)。
  • remove将Fragment移除,如果他有view,那么同时移除他的view。
  • replace替换容器中已存在的Fragment,这个方法的效果和先调用remove再调用add方法相同。
  • hide隐藏已存在的Fragment,这个方法只和那些视图被他添加进容器中的Fragment有关(因为这个方法效果是隐藏视图)。
  • show显示之前隐藏的Fragment,这个方法只和那些视图被他添加进容器中的Fragment有关(因为这个方法效果是显示视图)。
  • detach:从UI中分离Fragment,效果和将Fragment放入退回栈相同(退回栈下一篇会提到)。Fragment的UI被移除,但是FragmentManager还是管理着他的状态。这个状态只是销毁Fragment的视图。
  • attach:在Fragment从UI中分离之后,重新创建其视图结构,并和UI关联,且显示在界面上

以上便是FragmentTransaction所常用到的几个方法,他们都是负责Fragment的显示状态。主要的话我用红字标出来了,良心翻译,大家应该能够看懂。

有一点一定要说一下:上面的attach和detach千万不要跟Fragment的生命周期方法搞混了!重要的事说三遍!!

五、FragmentTransaction方法对应的Fragment生命周期方法

我们上面说到了FragmentTransaction的相关方法,我们可以看到都是对Fragment状态的调整(创建、显示、隐藏、销毁),这不正是对应着Fragment的生命周期么,以下是对应方法所涉及到的生命周期:

add:onAttach -> onCreate -> onCreateView -> onViewCreated(如果同时创建了view视图会调用-> onActivityCreated -> onStart->onResume

removeonPause -> onStop -> onDestroyView -> onDestroy -> onDetach

replace:这个就不多说了,上面两个合体。

hide/show:这两个方法不会调用Fragment任何生命周期方法:因为他只是显示和隐藏Fragment,有同学可能会说会调用onPause -> onStop 方法,但是不会。因为这几个对应的方法都是和Activity生命周期方法绑定的,而我们只是隐藏了Fragment,但是Activity还是在获取课焦点的状态(onResume),所以不会。

detach:onPause -> onStop -> onDestoryView 。

attach:onCreateView -> onViewCreated -> onActivityCreated -> onStart -> onResume


以上便是我们今天所涉及的全部内容,关于下一篇中会给大家带来关于Fragment更多的内容:Fragment详解(2)

喜欢的朋友可以关注一波,有不同观点和建议的可以评论留言。

谢谢大家支持!


猜你喜欢

转载自blog.csdn.net/zy_jibai/article/details/80627044
今日推荐