Android Fragment 详解

一:介绍:碎片(Fragment)是一种可以嵌入在活动(Activity)当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用的非常广泛。它和活动实在是太像了,同样都能包含布局,同样都有自己的生命周期。你甚至可以将碎片理解成一个迷你型的活动,虽然这个迷你型的活动有可能和普通的活动是一样大的。—— 摘抄自《Android第一行代码》

二:生命周期:如下图
在这里插入图片描述
与Activity不同的方法
onAttach():与Activity发生关联是被调用
onCreateView():初始化Fragment布局的时候会被调用
onActivityCreate():当Activity的onCreate方法返回时调用
onDestoryView():当该Fragment的视图被移除时调用
onDetach():当Fragment与Activity关联被取消时调用

三:用途:①:模块化由于Fragment 可以嵌套在Activity中,并可以运用添加、替换、移除Fragment等操作对Fragment的视图布局进行显示与隐藏。所以,在一个业务模块中,采用单Activity多个Fragment的布局结构,可以方便管理,并且减轻布局的层级绘制以及性能优化。
四:使用
1.静态使用Fragment(虽然在平时项目中基本没有这样使用过)
要点
①:使用< fragment></ fragment>标签
②:使用name: fragment类所在的名称

ShowOneActivity.java

package com.example.fragmentlearn;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class ShowOneActivity extends AppCompatActivity {

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

activity_show_one.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="com.example.fragmentlearn.ShowOneActivity">

    <fragment
        android:id="@+id/fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.example.fragmentlearn.FragmentOne"
        />
</android.support.constraint.ConstraintLayout>

在这里插入图片描述
2.动态使用Fragment

①:常用API
android.support.v4.app.FragmentManager:用于操作Fragment
android.support.v4.app.FragmentTransaction:保证操作Fragment的原子性

②:获取FragmentManager()
在Activity中:FragmentManager fm = getSupportFragmentManager()
在Fragment中:FragmentManager fm = getChildFragmentManager()
而不是getFragmentManager()。
③:通过Trasaction操作Fragment的添加、替换、移除、显示、隐藏、关联、解除关联。
FragmentTransaction transaction = fm.benginTransatcion();//开启一个事务

transaction.add()
向Activity中添加一个Fragment.

transaction.remove()
从Activity中移除一个Fragment,如果这个Fragment没有被添加到回退栈,则会销毁实例。(此操作会 销毁视图、销毁实例)

transaction.replace()
将Fragment替换为另一个Fragment,是remove及add的合体操作.(此操作会 销毁视图、销毁实例)

transaction.attach()
将detach的fragment重新关联到视图上,与detach()对应

transaction.detach();
将Activity视图上的Fragment解除关联,但不销毁实例(此操作会 销毁视图,不销毁实例)

transaction.show();
显示之前隐藏的Fragment,与hide()对应

transaction.hide();
隐藏当前显示的Fragment (此操作不会 销毁视图、不销毁实例)
问题:当transaction.hide() 与transaction.detach()或者transaction.remove()的效果相同时,该如何进行选择呢?
:此时,需要根据自己的业务场景,是否需要销毁视图或者实例来进行选择。
举例:例如需要保存用户的数据,使用transaction.hide(),比如控件EditText,当不销毁视图的时候,当用户填写内容后,再次显示的时候,EditText上填写的内容依然存在。但若不想保存用户的数据,则使用transaction.detach()或者transaction.remove(),再次显示的时候会重新创建视图,刚刚的内容也不会被保存。
这里需要注意,transaction.remove()则将实例也一并销毁,在显示的时候,需要重新new Fragment ()。而transaction.detach()则可以将实例放入回退栈中,下次通过fm.findViewByTag()进行取出。

使用案例

简单案例一:动态显示Fragment
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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="com.example.fragmentlearn.MainActivity">

    <FrameLayout
        android:id="@+id/container_fl"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/showFragmentOneBtn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="showOneFragment"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent" />
</android.support.constraint.ConstraintLayout>

MainActivity.class

public class MainActivity extends AppCompatActivity   {
    private static final String TAG = "MainActivity";
    private FragmentOne mFragmentOne;
     private final String FRAG_ONE = "oneFragment";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        Log.i(TAG, "onCreate: ");
    }

    private void initView() {
        Button showOneFragmentBtn = (Button) findViewById(R.id.showFragmentOneBtn);
        showOneFragmentBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                mFragmentOne = new FragmentOne();
                ft.add(R.id.container_fl,mFragmentOne,FRAG_ONE);
                ft.commit();
            }
        });
}

FragmentOne.java

package com.example.fragmentlearn;

import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class FragmentOne extends BaseFragement {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView: ");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }


}

fragment_one.xml

 <FrameLayout 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"
    tools:context="com.example.fragmentlearn.FragmentOne">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Fragment One" />

</FrameLayout>

简单案例二:显示及隐藏Fragment:
在这里插入图片描述
FragmentOne的生命周期:当隐藏的时候,并没有任何变化,因为视图并没有被销毁,显示时又重新显示。

07-28 15:08:36.603 2742-2742/com.example.fragmentlearn I/FragmentOne: onAttach: 
07-28 15:08:36.603 2742-2742/com.example.fragmentlearn I/FragmentOne: onCreate: 
07-28 15:08:36.603 2742-2742/com.example.fragmentlearn I/FragmentOne:  onCreateView: 
07-28 15:08:36.617 2742-2742/com.example.fragmentlearn I/FragmentOne: onActivityCreated: 
07-28 15:08:36.617 2742-2742/com.example.fragmentlearn I/FragmentOne: onStart: 
07-28 15:08:36.617 2742-2742/com.example.fragmentlearn I/FragmentOne: onResume: 

showOneActivity.java

package com.example.fragmentlearn;

import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class ShowOneActivity extends AppCompatActivity implements View.OnClickListener {
    private FragmentOne mFragmentOne;
    private static final String FRAG_ONE = "fragmentOne";

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

    private void initView() {
        Button showBtn = (Button) findViewById(R.id.showFragmentBtn);
        Button hideBtn = (Button) findViewById(R.id.hideFragmentBtn);
        showBtn.setOnClickListener(this);
        hideBtn.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        switch (v.getId()) {
            case R.id.showFragmentBtn:
                if (mFragmentOne == null) {
                    mFragmentOne = new FragmentOne();
                    ft.add(R.id.container_fl, mFragmentOne, FRAG_ONE);
                } else {
                    ft.show(mFragmentOne);
                }
                break;
            case R.id.hideFragmentBtn:
                if (mFragmentOne != null && mFragmentOne.isAdded()) {
                    ft.hide(mFragmentOne);
                }
                break;
            default:
        }
        ft.commit();
    }
}

activity_show_one.xml

<?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"
    tools:context="com.example.fragmentlearn.ShowOneActivity">

    <Button
        android:id="@+id/showFragmentBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="showOneFragment"
        android:textAllCaps="false" />

    <Button
        android:id="@+id/hideFragmentBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/showFragmentBtn"
        android:text="hideOneFragment"
        android:textAllCaps="false" />

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

</RelativeLayout>

FragmentOne.java


public class FragmentOne extends BaseFragement {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Log.i(TAG, " onCreateView: ");
        status.append(TAG + " onCreateView");
        return inflater.inflate(R.layout.fragment_one, container, false);
    }


}

fragment_one.xml

<FrameLayout 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"
    tools:context="com.example.fragmentlearn.FragmentOne">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Fragment One" />
    <EditText
        android:hint="EditText"
        android:layout_gravity="bottom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</FrameLayout>

简单实例三:关联及解除关联Fragment
EditText中的View在进行重新关联的时候会清除已经填写的数据内容

attach:
07-28 15:18:47.599 9624-9624/com.example.fragmentlearn I/FragmentOne: onAttach: 
07-28 15:18:47.599 9624-9624/com.example.fragmentlearn I/FragmentOne: onCreate: 
07-28 15:18:47.599 9624-9624/com.example.fragmentlearn I/FragmentOne: onCreateView: 
07-28 15:18:47.602 9624-9624/com.example.fragmentlearn I/FragmentOne: onActivityCreated: 
07-28 15:18:47.602 9624-9624/com.example.fragmentlearn I/FragmentOne: onStart: 
07-28 15:18:47.602 9624-9624/com.example.fragmentlearn I/FragmentOne: 
detach: 
07-28 15:18:48.439 9624-9624/com.example.fragmentlearn I/FragmentOne: onPause: 
07-28 15:18:48.439 9624-9624/com.example.fragmentlearn I/FragmentOne: onStop: 
07-28 15:18:48.439 9624-9624/com.example.fragmentlearn I/FragmentOne: onDestroyView: 
attach:
07-28 15:18:50.013 9624-9624/com.example.fragmentlearn I/FragmentOne: onCreateView: 
07-28 15:18:50.019 9624-9624/com.example.fragmentlearn I/FragmentOne: onActivityCreated: 
07-28 15:18:50.019 9624-9624/com.example.fragmentlearn I/FragmentOne: onStart: 
07-28 15:18:50.019 9624-9624/com.example.fragmentlearn I/FragmentOne: onResume: 

ShowOneActivity.java 更改部分:

 switch (v.getId()) {
            case R.id.showFragmentBtn:
                if (mFragmentOne == null) {
                    mFragmentOne = new FragmentOne();
                    ft.add(R.id.container_fl, mFragmentOne, FRAG_ONE);
                } else {
                    ft.attach(mFragmentOne);
                }
                break;
            case R.id.hideFragmentBtn:
                if (mFragmentOne != null && mFragmentOne.isAdded()) {
                    ft.detach(mFragmentOne);
                }
                break;
            default:

简单案例四:add remove Fragment

add:
07-28 15:27:11.728 18594-18594/com.example.fragmentlearn I/FragmentOne: onAttach: 
07-28 15:27:11.728 18594-18594/com.example.fragmentlearn I/FragmentOne: onCreate: 
07-28 15:27:11.728 18594-18594/com.example.fragmentlearn I/FragmentOne:  onCreateView: 
07-28 15:27:11.737 18594-18594/com.example.fragmentlearn I/FragmentOne: onActivityCreated: 
07-28 15:27:11.737 18594-18594/com.example.fragmentlearn I/FragmentOne: onStart: 
07-28 15:27:11.737 18594-18594/com.example.fragmentlearn I/FragmentOne: onResume: 
remove:
07-28 15:27:12.702 18594-18594/com.example.fragmentlearn I/FragmentOne: onPause: 
07-28 15:27:12.702 18594-18594/com.example.fragmentlearn I/FragmentOne: onStop: 
07-28 15:27:12.702 18594-18594/com.example.fragmentlearn I/FragmentOne: onDestroyView: 
07-28 15:27:12.702 18594-18594/com.example.fragmentlearn I/FragmentOne: onDestroy: 
07-28 15:27:12.702 18594-18594/com.example.fragmentlearn I/FragmentOne: onDetach:

ShowOneActivity.java 更改部分

 case R.id.showFragmentBtn:
                if (mFragmentOne == null) {
                    mFragmentOne = new FragmentOne();
                }
                ft.add(R.id.container_fl, mFragmentOne, FRAG_ONE);
                break;
            case R.id.hideFragmentBtn:
                if (mFragmentOne == null) {
                    mFragmentOne = new FragmentOne();
                }
                ft.remove(mFragmentOne);
                break;
            default:

简单案例五:简单封装显示Fragment

  private BaseFragment mPreFragment;
  public void showFragment(int resId, BaseFragment curFragment, String curFragmentTag) {
        FragmentManager fm = getChildFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        if (fm.findFragmentByTag(curFragmentTag) == null) {
            ft.add(resId, curFragment, curFragmentTag);
            Logger.d(Logger._JN, "add ");
        }
        if (mPreFragment != null && mPreFragment.isVisible()) {
            ft.hide(mPreFragment);
            Logger.d(Logger._JN, "hide ");
        }
        ft.show(curFragment);
        mPreFragment = curFragment;
        ft.commit();
    }

使用:

    private void initView() {
        mFragmentOne = new FragmentOne();
        mFragmentTwo = new FragmentTwo();
    }

	switch (v.getId()) {
            case R.id.showFragmentOneBtn:
                showFragment(R.id.container_fl,mFragmentTwo,mFragmentOne,FRAG_ONE);
                break;
            case R.id.showFragmentTwoBtn:
                showFragment(R.id.container_fl,mFragmentOne,mFragmentTwo,FRAG_TWO);
                break;
            default:
        }

回退栈介绍
介绍:类似于Activity,当用户在点击后退键时,系统会将Activity保存起来,Fragment也有这种功能,不过我们要显示的调用addToBackStack()方法进行保存。
用途:保留Fragment的实例,当按返回键的时候,可以返回到上一个添加到回退栈中的Fragment中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值