第一行代码第四章 碎片

4.1基本概念

● Fragment是依赖于Activity的,不能独立存在的。
● 一个Activity里可以有多个Fragment。
● 一个Fragment可以被多个Activity重用。
● Fragment有自己的生命周期,并能接收输入事件。
● 我们能在Activity运行时动态地添加或删除Fragment。

4.2生命周期

Fragment的生命周期和Activity类似,但比Activity的生命周期复杂一些,基本的生命周期方法如下图:
在这里插入图片描述

4.2.1 Fragment 生命周期中的每个方法的意义与作用

●onAttach():Fragment和Activity相关联时调用。且仅调用一次,可以通过该方法获取Activity引用,还可以通过getArguments()获取参数。 调用此方法时,Fragment与Activity已完成绑定。

● onCreate():Fragment最初创建时调用。初始化Fragment,可通过savedInstanceState 获取之前保存的值。

● View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
在准备绘制Fragment界面时调用,返回值为Fragment要绘制布局的根视图,当然也可以返回null。注意使用inflater构建View时一定要将attachToRoot指明false,因为Fragment会自动将视图添加到container中,attachToRoot为true会重复添加报错。onCreateView并不是一定会被调用,当添加的是没有界面的Fragment就不会调用,比如调用FragmentTransaction的 add(Fragment fragment, String tag)方法。

● onActivityCreated():当Activity完成onCreate()时调用。

● onStart():当Fragment可见时调用。Fragment有不可见变为可见状态

● onResume():当Fragment可见且可交互时调用。ragment处于活动状态,用户可与之交互。

● onPause():当Fragment不可交互但可见时调用。

● onStop():当Fragment不可见时调用。

● onDestroyView():当Fragment的UI从视图结构中移除时调用。

● onDestroy():销毁Fragment时调用。

● onDetach():当Fragment和Activity解除关联时调用。

上面的方法中,只有onCreateView()在重写时不用写super方法,其他都需要。
图中有一条从onDestroyView指向onCreatedView的线,意思是Fragment从back栈(存放Fragment的栈)回到前台时经历的生命周期。

4.2.2Activity 生命周期对Fragment生命周期的影响

将Fragment生命周期中每个回调单独讲完之后,下面就来看看Fragment生命周期和Activity生命周期之前的联系,这里也有一张十分经典的官方图。
在这里插入图片描述
可以十分明了的看到,当Activity处于不同生命周期时Fragment生命周期的流程。需要关注一下两者生命周期顺序问题,其中onCreate、onStart、onResume都是Activity先调用之后才是Fragment,onPause、onStop、onDestroy(在Fragment中是onDetach),是先Fragment调用之后才是Activity。

Fragment相关操作对生命周期的影响

添加Fragment可以分为静态添加动态添加两大类。
● 静态添加是在XML中直接添加Fragment,简单方便,缺点是添加之后不能在删除。
● 动态添加是在代码中FragmentManger使用一系列FragmentTransaction事务操作动态控制,灵活多变。一般都是使用动态添加,下面就讲讲动态添加有关的生命周期。

1.add:onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume

2.remove:onPause->onStop->onDestroyView->onDestroy->onDetach

3.show:onHiddenChanged(boolean hidden) hidden为false

4.hide:onHiddenChanged(boolean hidden) hidden为true

5.replace:旧Fragment的remove生命周期->新Fragment的add生命周期

6.replace+addToBackStack:onPause->onStop->onDestroyView->新Fragment的add生命周期
之后点击back:新Fragment的remove->onCreateView->onViewCreated->onActivityCreated->onStart->onResume 就是第一张图的线

7. detach:onPause->onStop->onDestroyView 可以看到只是视图被移除,Fragment关联状态还是不变,还是处于FragmentManger的管理下

8.FragmentTransaction.attach(Fragment var1):onStart->onResume->onCreateView

4.2.1静态加载碎片

使用标签在布局中添加碎片:

  1. android:name属于来显式指明要添加的碎片类名
  2. 添加id 属性(不添加会报错)
    静态加载碎片直接在xml,中加载

例子:在Activiy中左右加载两个碎片

left.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00">
</LinearLayout>

fragement_left.java

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
    
    
    View view = inflater.inflate(R.layout.left,container,false);
    return view;
    }

right.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</LinearLayout>

fragement_right.java

    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
    
    
        View view = inflater.inflate(R.layout.right,container,false);
        return view;
    }

主界面加载:
activity_main.xml

<?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"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/left_fragement"
        android:layout_width="0dp"
        android:name="com.example.myapplication.frame_left"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </fragment>
    <fragment
        android:id="@+id/right_fragement"
        android:layout_width="0dp"
        android:name="com.example.myapplication.frame_right"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </fragment>
</LinearLayout>

效果
在这里插入图片描述

4.2.2 动态添加碎片

碎片不仅可以在xml中静态加载,还可以在程序运行时动态地添加到活动中。

动态添加碎片的步骤:
● 创建待添加的碎片实例
● 获取FragementManager在活动中调用getSupportFragmentManager()方法来获取
● 开启事务,调用beginTransaction()方法来开启一个事务
● 向容器内添加或替换碎片,一般使用replace()方法实现,需要传入容器的id和待添加的碎片实例
● 提交事务,调用commit()方法来完成

在上面的基础上,新建一个another_fragement.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffff00"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:textSize="20sp"
        android:text="This is another right fragment"/>

</LinearLayout>

创建AnotherRightFragment类: 将布局引进来

public class AnotherRightFragment extends Fragment {
    
    

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    

        View view = inflater.inflate(R.layout.another_right_fragment, container, false);
        return view;
    }
}

修改activity_main.xml文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/left_fragment"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
    
    <FrameLayout
        android:id="@+id/right_layout"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

</LinearLayout>

在代码中向FrameLayout里添加内容,从而实现动态添加碎片的功能。

修改MainActivity中的代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
        replaceFragment(new RightFragment());
    }

    @Override
    public void onClick(View v) {
    
    
        switch (v.getId()) {
    
    
            case R.id.button:
                replaceFragment(new AnotherRightFragment());
                break;
            default:
                break;
        }
    }


    private void replaceFragment(Fragment fragment) {
    
    
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.commit();
    }
}

通过点击左侧fragement中的button ,来实现右侧fragement 进行切换

效果图:
运行程序,效果图如下:
在这里插入图片描述

4.2.3 在碎片中模拟返回栈

上面通过点击按钮添加一个碎片后,如果此时按下Back键程序就会直接退出。如果想要模范返回栈的效果,返回到上一个碎片,则需要在提交事务之前调用addToBackStack()方法。
addToBackStack中一般填写null

private void replaceFragment(Fragment fragment) {
    
    
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.replace(R.id.right_layout, fragment);
    transaction.addToBackStack(null);
    transaction.commit();
}

猜你喜欢

转载自blog.csdn.net/weixin_41477306/article/details/105477088