Android Fragment源码分析Add方法
作者:Android技术栈 发布时间:2023-02-12 19:13:58
前言
本篇我们就来讲讲Fragment管理中的 Add() 方法
Add()
在我们动态的添加、管理Fragment中,Add属于最基础的方法了; 用法也很简单,如下就是向Activity添加一个Fragment:
getSupportFragmentManager().beginTransaction().add(R.id.fragmenta,new FragmentA()).commit();
一般时候我们使用到Fragment的时候,都是不止一个,比如微信界面,底部导航有四个按钮,分别对应不同的四个Fragment,像这种的每点击一次底部按钮就切换一下界面的话,我们就可以使用Add()外加hide和show进行组合
下面我们简单实现一下,这里我们就弄两个Fragment,
这里我们的MainActivity的布局如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.shaoen.lenovo.myapplication.MainActivity">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="@+id/fragmenta"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/fragmenta_button"
android:text="FragmentA"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<Button
android:id="@+id/fragmentb_button"
android:text="FragmentB"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
下面看MainActivity的内容:
package com.shaoen.lenovo.myapplication;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.shaoen.lenovo.myapplication.fragment.FragmentA;
import com.shaoen.lenovo.myapplication.fragment.FragmentB;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private String TAG=MainActivity.class.getSimpleName();
private Button fragmentA_Button;
private Button fragmentB_Button;
private FragmentTransaction transaction;
private FragmentManager fragmentManager;
private Fragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"onCreate--执行了");
setContentView(R.layout.activity_main);
fragmentManager=getSupportFragmentManager();
transaction= fragmentManager.beginTransaction();
fragment=new FragmentA();
transaction.add(R.id.fragmenta,fragment,"FragmentA").commit();
fragmentA_Button=(Button) findViewById(R.id.fragmenta_button);
fragmentB_Button=(Button) findViewById(R.id.fragmentb_button);
fragmentA_Button.setOnClickListener(this);
fragmentB_Button.setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG,"onStart--执行了");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG,"onResume--执行了");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG,"onPause--执行了");
}
@Override
protected void onStop() {
super.onStop();
Log.i(TAG,"onStop--执行了");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG,"onDestroy--执行了");
}
@Override
public void onClick(View v) {
transaction= fragmentManager.beginTransaction();
switch (v.getId()){
case R.id.fragmenta_button:
if (fragment!=null)
transaction.hide(fragment);
fragment= fragmentManager.findFragmentByTag("FragmentA");
if (fragment!=null){
transaction.show(fragment);
}
else {
fragment=new FragmentA();
transaction.add(R.id.fragmenta,fragment,"FragmentA").commit();
}
break;
case R.id.fragmentb_button:
if (fragment!=null)
transaction.hide(fragment);
fragment= fragmentManager.findFragmentByTag("FragmentB");
if (fragment!=null){
transaction.show(fragment);
}
else {
fragment=new FragmentB();
transaction.add(R.id.fragmenta,fragment,"FragmentB").commit();
}
break;
}
}
}
这里我们写的比较简单,主要是为了看一下他们的执行生命周期,在这里我把所以log都打印出来了
刚开始运行时的log如下:
I/MainActivity: onCreate--执行了
I/FragmentA: onAttach--执行了
I/FragmentA: onCreate--执行了
I/FragmentA: onCreateView--执行了
I/FragmentA: onActivityCreated--执行了
I/FragmentA: onStart--执行了
I/MainActivity: onStart--执行了
I/MainActivity: onResume--执行了
I/FragmentA: onResume--执行了
此时我们点击FragmentB按钮;
I/FragmentB: onAttach--执行了
I/FragmentB: onCreate--执行了
I/FragmentB: onCreateView--执行了
I/FragmentB: onActivityCreated--执行了
I/FragmentB: onStart--执行了
I/FragmentB: onResume--执行了
然后我们在反复点击FragmentA和FragmentB按钮,发现没有任何log打印,此时证明FragmentA和FragmentB通过hide和show方法进行切换时,都只会初始化一次,
下面我们看向replace这个方法
replace:
首先replace方法,其实是remove和add方法的组合; remove就是将一个Fragment从FragmentManager中删除,如果我们切换下一个Fragment时,上一个Fragment不需要了,可以直接使用replace,如果我们还需要的话,API中也提供了相应的方法,那就是加入回退栈addToBackStack()
下面我们把MainActivity中的代码改一下:
@Override
public void onClick(View v) {
transaction= fragmentManager.beginTransaction();
switch (v.getId()){
case R.id.fragmenta_button:
if (fragment!=null)
transaction.hide(fragment);
fragment= fragmentManager.findFragmentByTag("FragmentA");
if (fragment!=null){ Log.i(TAG,"fragment不为空");
transaction.show(fragment);
}
else {
Log.i(TAG,"fragment为空");
fragment=new FragmentA();
transaction.replace(R.id.fragmenta,fragment,"FragmentA").addToBackStack("FragmentA").commit();
}
break;
case R.id.fragmentb_button:
if (fragment!=null)
transaction.hide(fragment);
fragment= fragmentManager.findFragmentByTag("FragmentB");
if (fragment!=null){
Log.i(TAG,"fragment不为空");
transaction.show(fragment);
}
else {
Log.i(TAG,"fragment为空");
fragment=new FragmentB();
transaction.replace(R.id.fragmenta,fragment,"FragmentB").addToBackStack("FragmentB").commit();
}
break;
}
}
这里我们就改了一下OnClick中的代码,这时我们再打印一下log看看:
首先初始化时是一致的:
这里写代码片
此时我们点击FragmentB:
12-18 21:48:14.227 21081-21081/com.shaoen.lenovo.myapplication I/MainActivity: fragment为空
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onPause--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onStop--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onDestroyView--执行了
12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onAttach--执行了
12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreate--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreateView--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onActivityCreated--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onStart--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onResume--执行了
我们发现Fragment调用了destroy方法,此时我们再点击FragmentA:
I/MainActivity: fragment不为空
此时发现FragmentA没有切换过来,这是因为,我们在FragmentManager中找到了FragmentA的实例,但是此时,FragmentA的界面已经被销毁了,所以我们看见的还是FragmentB,此时我们的OnClick改成如下:
@Override
public void onClick(View v) {
transaction= fragmentManager.beginTransaction();
switch (v.getId()){
case R.id.fragmenta_button:
fragment=new FragmentA();
transaction.replace(R.id.fragmenta,fragment,"FragmentA").addToBackStack("FragmentA").commit();
break;
case R.id.fragmentb_button:
fragment=new FragmentB();
transaction.replace(R.id.fragmenta,fragment,"FragmentB").addToBackStack("FragmentB").commit();
break;
}
}
这时再打印一下log,
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onPause--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onStop--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onDestroyView--执行了
12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onAttach--执行了
12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreate--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onCreateView--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onActivityCreated--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onStart--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onResume--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onPause--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onStop--执行了
12-18 21:48:14.228 21081-21081/com.shaoen.lenovo.myapplication I/FragmentB: onDestroyView--执行了
12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onAttach--执行了
12-18 21:48:14.229 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onCreate--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onCreateView--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onActivityCreated--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onStart--执行了
12-18 21:48:14.250 21081-21081/com.shaoen.lenovo.myapplication I/FragmentA: onResume--执行了
此时发现每次切换时,都会调用Fragment都会重新调用onCreateView()到onDestroyView()的所有方法,其实就是Fragment的布局层整个销毁到重建的过程
注: 当我们进行Fragment嵌套时,如果我们点击返回键,不想回到上一个Fragment,而想直接回到更往前一个,或者更往前的Fragment,我们可以使用FragmentManager.popBackStackImmediate (String tag, int flags)方法,弹出TAG为tag的Fragment,同时把此Fragment以上的Fragment全都弹出(弹出回退栈,即彻底销毁,detach)
来源:https://blog.csdn.net/m0_70748845/article/details/126246670


猜你喜欢
- 前言定时任务动态管理分为两种方式:方式一:Web前台配置Trigger触发器(关联Cron)、ThreadPoolTaskScheduler
- 本文实例为大家分享了Dijkstra算法实现校园导游程序的具体代码,供大家参考,具体内容如下应用设计性实验1.问题描述校网导游程序: 一个校
- 服务限流,是指通过控制请求的速率或次数来达到保护服务的目的,在微服务中,我们通常会将它和熔断、降级搭配在一起使用,来避免瞬时的大量请求对系统
- 本文实例讲述了C#使用foreach遍历哈希表(hashtable)的方法。分享给大家供大家参考。具体实现方法如下:using System
- 自定义过滤器获取不到session根本原因,多个自定义过滤器执行顺序问题问题action请求中request对象为ShiroHttpServ
- 序言当我们要同时启用多个项目而又要使用不同端口或者变换配置属性时,我们可以在配置文件中设置${变量名}的变量来获取启动时传入的参数,从而实现
- 之前在学习RecyclerView的时候,建立了一个可以滑动的View列表,但是当滑动距离过长的时候,需要手动返回到顶部,于是加了一个一键返
- float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal。而且使用BigDe
- 面试题1:你们是怎样保存用户密码等敏感数据的?本题回答参考朱晔的《Java业务开发常见错误100例》我们知道,用户名、密码、身份证等都属于用
- 把验证码存储在Cookie中一般来说,我们会把验证码的值用Session存储起来,通过对比用户提交的验证码和Session中的验证码,就可以
- 编写C#程序的时候,我们都遇到过配置文件,而如今绝大多数的配置文件都是用XML写的。所以在处理的时候就需要操作XML文件。那么C#如何操作X
- Android 6.0版本对于程序员兄弟来说最不友好的就是权限的问题,动态权限的设置曾经让我很苦恼,目前大部分关于6.0权限设置的框架基本都
- java 实现随机数组输出及求和问题描述:随机生成10个数,填充一个数组,然后用消息框显示数组内容,接着计算数组元素的和,将结果也显示在消息
- 一、LINQ的体系结构语言集成查询 (LINQ) (C#) | Microsoft 官方文档LINQ总共包括五个部分: 程序集命名
- 目录一、准备工作1、导包二、了解注解1、常用注解2、@ExcelProperty注解3、@ColumnWith注解4、@ContentFon
- 一.前言在日常的开发中,经常需要对方法参数进行校验(非空、长度等)。如果采用hardcode去校验(if..else..),会造成代码冗余,
- 半路开始看的朋友可以回顾一下前几篇java并发编程专题(一)----线程基础知识java并发编程专题(二)----如何创建并运行java线程
- 在java中类之间也是有着继承关系的,就我们之前有提到不少父类与子类的一些问题。 讲的以子类的调用为主,那么有小伙伴知道父类的调用方法吗?这
- 一般表单数据分为两类<form method="post" action="${pageContext.
- 本文实例为大家分享了Android实现蓝牙原理代码,供大家参考,具体内容如下package com.example.se7en.testbl