当前位置:网站首页>从源码方面来分析Fragment管理中 Add() 方法
从源码方面来分析Fragment管理中 Add() 方法
2022-08-09 21:51:00 【Android技术栈】
前言
本篇我们就来讲讲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)
有需要文章中完整代码的同学:现在私信发送 “底层源码” 即可免费获取
现在私信发送 “进阶” 还可以获取《更多 Android 源码解析+核心笔记+面试真题》
最后我想说:
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们
技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面
Android 架构师之路还很漫长,与君共勉
边栏推荐
- TF中random.normal()与random.truncated_normal()
- Converting angles to radians
- Install Mysql8.0 on windos, and solve the problem of re-login exception ERROR 1045 (28000)
- STC8H development (15): GPIO drive Ci24R1 wireless module
- 【双链表增删查改接口的实现】
- Deceptive Dice(期望计算)
- 自监督学习 —— MoCo v2
- linux定时执行sql文件[通俗易懂]
- Daily practice of PMP | Do not get lost in the exam -8.8 (including agility + multiple choice)
- hdu 1503 Advanced Fruits(最长公共子序列的应用)
猜你喜欢
Quotefancy ,提供鼓舞人心语录的壁纸网站 - 倾城之链
微软word怎么转换成pdf文件?微软word转换为pdf格式的方法
2.1.5 大纲显示问题
【云原生】4.2 DevOps 精讲篇
Word怎么制作双面席卡?使用Word制作双面席卡方法
Interpretation of the paper (DropEdge) "DropEdge: Towards Deep Graph Convolutional Networks on Node Classification"
Word文档怎么输入无穷大符号∞
“稚晖君”为2022昇腾AI创新大赛打call&nbsp;期待广大开发者加入
POWER SOURCE ETA ETA Power Repair FHG24SX-U Overview
Problems with compiling SIP with QGIS
随机推荐
POWER SOURCE ETA ETA Power Repair FHG24SX-U Overview
TF生成均匀分布的tensor
【EF】数据表全部字段更新与部分字段更新
角度和弧度的相互换算
Don't tell me to play, I'm taking the PMP exam: what you need to know about choosing an institution for the PMP exam
“稚晖君”为2022昇腾AI创新大赛打call&nbsp;期待广大开发者加入
MySQL跨表、多表更新SQL语句总结
【云原生】4.2 DevOps 精讲篇
Word怎么制作一张标准的答题卡?
L3-2 Delete up to three characters (30 points)
1215 – Cannot add foreign key constraint
Word怎么设置图片衬于文字下方?两种方法教你设置Word图片衬于文字下方
Word文档怎么输入无穷大符号∞
NIO Cup 2022 Nioke Summer Multi-School Training Camp 7 CFGJ
Usage of placeholder function in Tensorflow
Tensorflow中使用convert_to_tensor去指定数据的类型
laravel table migration error [easy to understand]
mysql multi-table left link query
编译原理之文法
abstract class or interface