Android-Fragment知识详解

一、Fragment介绍

Activity界面中的一部分,可理解为模块化的Activity

1.Fragment不能独立存在,必须嵌入到Activity中
2.Fragment具有自己的生命周期,接收它自己的事件,并可以在Activity运行时被添加或删除
3.Fragment的生命周期直接受所在的Activity的影响。如:当Activity暂停时,它拥有的所有Fragment们都暂停

二、Fragment生命周期

1. 生命周期流程 & 方法详解

在这里插入图片描述

2. 常见场景的生命周期调用方式

在这里插入图片描述

三、Fragment具体使用

由于Fragment作为Activity一部分,所以Fragment的使用一般是添加到Activity中
将Fragment添加到Activity中一般有2种方法:

  • 在Activity的layout.xml布局文件中静态添加
  • 在Activity的.java文件中动态添加

方法1:静态加载Fragment

(1)创建Fragment布局文件
left_fragment.xml

<?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">
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Button"/>
</LinearLayout>

right_fragment.xml

<?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="#B9D6E3">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="25sp"
        android:text="This is right Fragment"/>
</LinearLayout>

(2)自定义一个Fragment类
继承Fragment或者他的子类,重写onCreateView()方法 在该方法中调用:inflater.inflate()方法加载Fragment的布局文件,接着返回加载的view对象

public class LeftFragment extends Fragment {
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //加载布局
        View view = inflater.inflate(R.layout.left_fragment, container, false);
        return view;
    }
}

public class RightFragment extends Fragment {
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.right_fragment,container,false);
        return view;
    }
}

inflate(int resource, @Nullable ViewGroup root, boolean attachToRoot) :加载布局文件

  • 第一个参数:要加载的布局文件
  • 第二个参数:第一个参数的父布局
  • 第三个参数:
    (1)true:表示将第一个参数表示的布局添加到第二个参数的布局中
    (2)false:不把第一个参数的布局添加到第二个参数的布局中

(3)在需要加载Fragment的Activity对应的布局文件中添加fragment的标签
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_frag"
        android:name="com.example.fragmenttest.LeftFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
    <fragment
        android:id="@+id/right_frag"
        android:name="com.example.fragmenttest.RightFragment"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"/>
</LinearLayout>

<fragment>:在布局中添加碎片android:name:要添加的碎片的类名,该类名为全限定类名

(4)Activity在onCreate( )方法中调setContentView()加载布局文件即可MainActivity.java文件不修改

方法2:动态加载Fragment

(1)编写fragment布局文件
left_fragment.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E696B1">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="40sp"
        android:layout_marginLeft="20dp"
        android:textColor="#000000"
        android:text="这是本地视频"/>
</LinearLayout>

right_fragment.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#B9D6E3">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="40sp"
        android:layout_marginLeft="20dp"
        android:textColor="#000000"
        android:text="这是网络视频"/>
</LinearLayout>

(2)自定义一个Fragment类
继承Fragment或者他的子类,重写onCreateView()方法 在该方法中调用:inflater.inflate()方法加载Fragment的布局文件,接着返回加载的view对象

代码同静态加载

(3)编写activity.main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/menu1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="本地视频"
            android:gravity="center"
            android:textSize="30sp"/>
        <TextView
            android:id="@+id/menu2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="网络视频"
            android:gravity="center"
            android:textSize="30sp"/>
    </LinearLayout>
    <FrameLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8"/>
</LinearLayout>

(4)编写MainActivity逻辑
获得FragementManager对象——>开启事务,获得FragmentTransaction对象——>调用replace()方法添加碎片到容器——>提交事务

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private TextView menu1;
    private TextView menu2;
    private FrameLayout content;
    private FragmentManager fragmentManager;
    private FragmentTransaction transaction;
    private Fragment fragment1;
    private Fragment fragment2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        //获得FragmentManager对象
        fragmentManager = getSupportFragmentManager();
        //开启事务,获得FragmentTransaction对象
        transaction = fragmentManager.beginTransaction();
        //创建需要添加的Fragment
        fragment1 = new LeftFragment();
        fragment2 = new RightFragment();
        //向容器内添加或替换碎片,默认情况下为LeftFragment
        transaction.replace(R.id.content,fragment1);
        //提交事务
        transaction.commit();
    }
    //初始化控件
    private void initView() {
        menu1 = (TextView)findViewById(R.id.menu1);
        menu2 = (TextView)findViewById(R.id.menu2);
        content = (FrameLayout) findViewById(R.id.content);
        menu1.setOnClickListener(this);
        menu2.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        transaction = fragmentManager.beginTransaction();
        switch (view.getId()){
            case R.id.menu1:
                //点击menu1,内容替换为leftFragment
                transaction.replace(R.id.content,fragment1);
                break;
            case R.id.menu2:
                //点击menu1,内容替换为RightFragment
                transaction.replace(R.id.content,fragment2);
                break;
            default:
                break;
        }
        transaction.commit();
    }
}

方法详解:

getSupportFragmentManager():获得FragmentManager
beginTransaction():开启事务,获得FragmentTransaction对象
replace(int containerViewId, Fragment fragment):向容器内添加碎片

第一个参数:要添加Fragment的容器
第二个参数:添加的Fragment实例


commit():提交事务

参考:Fragment的基本用法

四、Activity 与 Fragment 相互通信

4.1Activity如何传递数据到Fragment

  • 采用 Bundle方式。具体Demo步骤如下:

步骤1:Activity的布局文件
activcity_2_fragment.xml


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

    <TextView
        android:id="@+id/text"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:text="我是Activity" />

    <FrameLayout
        android:layout_below="@+id/button"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="500dp"/>
</LinearLayout>

步骤2:设置 Fragment的布局文件
fragment.xml

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

    <TextView
        android:id="@+id/fragment"
        android:text="我是fragment"
        android:layout_gravity="center"
        android:textSize="30dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

    <TextView
        android:id="@+id/text"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:text="等待Activity发送消息" />

    <Button
        android:id="@+id/button"
        android:layout_gravity="center"
        android:text="点击接收Activity消息"
        android:layout_centerInParent="true"
        android:textSize="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

步骤3:设置Activity的类文件
Activity2Fragment

public class Activity2Fragment extends AppCompatActivity {

    TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activcity_2_fragment);

        text = (TextView) findViewById(R.id.text);

        // 步骤1:获取FragmentManager
        FragmentManager fragmentManager = getFragmentManager();

        // 步骤2:获取FragmentTransaction
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        // 步骤3:创建需要添加的Fragment 
        final mFragment fragment = new mFragment();

        // 步骤4:创建Bundle对象
        // 作用:存储数据,并传递到Fragment中
        Bundle bundle = new Bundle();

        // 步骤5:往bundle中添加数据
        bundle.putString("message", "I love Google");

        // 步骤6:把数据设置到Fragment中
        fragment.setArguments(bundle);

        // 步骤7:动态添加fragment
        // 即将创建的fragment添加到Activity布局文件中定义的占位符中(FrameLayout)
        fragmentTransaction.add(R.id.fragment_container, fragment);
        fragmentTransaction.commit();


    }
}

步骤4:设置Fragment的类文件
mFragment.java

public class mFragment extends Fragment {
    Button button;
    TextView text;
    Bundle bundle;
    String message;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View contentView = inflater.inflate(R.layout.fragment, container, false);
        // 设置布局文件

        button = (Button) contentView.findViewById(R.id.button);
        text = (TextView) contentView.findViewById(R.id.text);

        // 步骤1:通过getArgments()获取从Activity传过来的全部值
        bundle = this.getArguments();

        // 步骤2:获取某一值
        message = bundle.getString("message");

        // 步骤3:设置按钮,将设置的值显示出来
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 显示传递过来的值
                text.setText(message);

            }
        });

        return contentView;
    }
}

在这里插入图片描述

4.2Fragment如何传递数据到Activity

  • 采用接口回调方式。

步骤1:在Activity的布局文件定义1占位符(FrameLayout)
activity_main.xml

<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="scut.carson_ho.fragment_2_activity.MainActivity">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20dp"
        android:text="等待Fragment发送消息" />

    <Button
        android:id="@+id/button"
        android:layout_below="@+id/text"
        android:text="点击接收Fragment消息"
        android:layout_centerInParent="true"
        android:textSize="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:layout_below="@+id/button"
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="500dp"/>

</RelativeLayout>

步骤2:设置Fragment的布局文件
fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <TextView
        android:id="@+id/fragment"
        android:text="我是fragment"
        android:gravity="center"
        android:textSize="30dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"/>

</LinearLayout>

步骤3:设置回调接口
该接口用于用于Activity与Fragment通信
ICallBack.java

public interface ICallBack {
    void get_message_from_Fragment(String string);

}

步骤4:设置Fragment的类文件
mFragment.java

public class mFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View contentView = inflater.inflate(R.layout.fragment, container, false);
        // 设置布局文件
        return contentView;
    }

    // 设置 接口回调 方法
    public void sendMessage(ICallBack callBack){

        callBack.get_message_from_Fragment("消息:我来自Fragment");

    }
}

步骤5:设置Acticvity的类文件
Main_Activity.java

public class MainActivity extends AppCompatActivity {

    Button button;
    TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button)findViewById(R.id.button);
        text = (TextView)findViewById(R.id.text);

        // 步骤1:获取FragmentManager
        FragmentManager fragmentManager = getFragmentManager();

        // 步骤2:获取FragmentTransaction
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();

        // 步骤3:创建需要添加的Fragment 
        final mFragment fragment = new mFragment();

        // 步骤4:动态添加fragment
        // 即将创建的fragment添加到Activity布局文件中定义的占位符中(FrameLayout)
        fragmentTransaction.add(R.id.fragment_container, fragment);
        fragmentTransaction.commit();


        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // 通过接口回调将消息从fragment发送到Activity
                fragment.sendMessage(new ICallBack() {
                    @Override
                    public void get_message_from_Fragment(String string) {
                            text.setText(string);
                    }
                });

            }
        });
    }
}

在这里插入图片描述

五、Fragment懒加载

一、要实现Fragment的懒加载需要满足三个条件

1、布局是否初始化

2、视图是否可见

3、是否加载过数据

综上所述,只要满足这三个条件就可以执行加载操作。

二、如何实现

1、定义一个 isPrepared变量,在初始化视图的时候赋值为true;

2、定义一个isVisibleToUser变量,在页面可见状态赋值为true;

3、定义一个isDataInitiated变量,在页面加载数据时赋值为true;

使用Fragment自带的setUserVisibleHint()来判断当前fragment是否对用户可见,根据回调的isVisibleToUser参数来进行相关的逻辑判断。创建一个变量isVisible来拿到fragment是否可见的标志。

但是直接根据isVisible判断就加载数据,很有可能很多控件在OnCreateView()方法还未执行完成的情况下出现NullPointerException空指针的情况。所以我们需要在控件初始化完成并且用户可见的时候,再去进行数据的加载。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值