【Android】Fragment与Activity间通信知识总结

文章目录

  • 一、Activity向Fragment通信
    • 1.1 通过方法
      • 1.1.1 构造方法
      • 1.1.1 普通public方法
    • 1.2 通过setArguments方法
    • 1.3 通过接口
  • 二、Fragment向Activity通信
    • 2.1 通过getActivity
    • 2.2 通过接口
  • 三、Fragment之间传递数据
    • 通过Activity中转

一、Activity向Fragment通信

1.1 通过方法

1.1.1 构造方法

就是在MainActivity进行动态注册时,把data通过构造方法传参的形式传给fragment,所以要对fragment类进行修改

  1. 修改Fragment
public class ExampleFragment2 extends Fragment {private static final String ARG_PARAM1 = "param1";private static final String ARG_PARAM2 = "param2";private String mParam1;private String mParam2;//保留空参构造public ExampleFragment2() {}//提供一个接收数据用的构造方法public ExampleFragment2(String param1) {mParam1 = param1;}//其他方法这里省略@Override// 在onViewCreated方法运行时,使用得到的数据public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);//获得mparam1的值后,修改textView的值if (!TextUtils.isEmpty(mParam1)) {TextView tv1 = view.findViewById(R.id.tv1);tv1.setText(mParam1);}}
}

onViewCreated 方法则是在视图创建完成后调用的,使用 onViewCreated 来处理视图相关的逻辑,确保视图已经完全创建并可用

  1. Activity中创建Fragment实例
  • 第一次创建时就传递
        if (savedInstanceState == null) {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();ExampleFragment2 fragment2 = new ExampleFragment2("这是我从碎片MainActivity传递的数据");fragmentTransaction.add(R.id.fragment_container2, fragment2).addToBackStack(null);fragmentTransaction.commit();}
  • 创建后想再次传递
 private void passDataByConstruct() {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();String data = "我的数据"ExampleFragment2 dataPassFragment = new ExampleFragment2(data);fragmentTransaction.replace(R.id.fragment_container2, dataPassFragment).commit();}

1.1.1 普通public方法

  1. Fragment 类中添加普通方法
public void setParam(String data) {mParam1 = data;if (!TextUtils.isEmpty(mParam1)) {tv1.setText(mParam1);}}
  1. Activity 中查找并调用 Fragment 的普通方法
private void passDataByConstruct2() {FragmentManager fragmentManager = getSupportFragmentManager();Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container2);if (fragment != null) {((ExampleFragment2) fragment).setParam("我的数据2--普通方法");}
}

注意如果没使用点击事件的话,passDataByConstruct2要在onResume阶段被调用

1.2 通过setArguments方法

Bundle是一个用于携带数据的键值对集合,它可以保存各种类型的数据,本身是一个实现了Parcelable接口的类,因此它可以被序列化以便在组件之间传递。

  1. Activity 中使用setArguments()方法
public void onClick3(View view) {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();// 创建一个新的ExampleFragment2实例ExampleFragment2 exampleFragment2 = new ExampleFragment2();// 创建一个Bundle对象,用于传递数据到新的片段Bundle bundle = new Bundle();// 向Bundle中添加字符串数据和整型数据bundle.putString("data", "我的数据3--Argument");bundle.putInt("int_data", 10);// 将Bundle对象设置为新的片段的参数exampleFragment2.setArguments(bundle);// 用新的片段替换布局中的片段容器,并提交此事务fragmentTransaction.replace(R.id.fragment_container2, exampleFragment2).commit();}
  1. Fragment使用getArguments()接收数据
//部分方法省略
public class ExampleFragment2 extends Fragment {private String mParam1;private String mParam2;TextView tv1;// 用于存储从外部传入的额外数据private String data1;private int data2;// 在Fragment创建时调用  @Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() != null) {mParam1 = getArguments().getString(ARG_PARAM1);mParam2 = getArguments().getString(ARG_PARAM2);// ----------------在这里---------------// 从参数中获取data1的值,这里"data""int_data"是键名  data1 = getArguments().getString("data");data2 = getArguments().getInt("int_data");}}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);tv1 = view.findViewById(R.id.tv1);//需要 在onViewCreated时进行修改,不然后tv1空指针异常if (!TextUtils.isEmpty(data1)) {tv1.setText(data1 + data2);}}
}

1.3 通过接口

利用观察者模式的思路实现

观察者模式是一种设计模式,涉及两个主要角色:

  1. 被观察者(Subject):维护一个观察者(Observer)列表,提供添加、移除观察者的方法,并在状态变化时通知所有观察者。
  2. 观察者(Observer):对被观察者感兴趣的对象,它们通过注册被观察者来接收通知。

image-20240727105142996

MainActivity作为被观察者

public class MainActivity extends AppCompatActivity {//fragment的动态注册省略public void onClick4(View view) {mDataChangeListener.onDataChange("我的数据4——接口");}//被观察者:数据源持有该引用private OnDataChangeListener mDataChangeListener;//这里接收的参数是任意实现了dataChangeListener接口的类的对象//目的是利用匿名内部类创建实现接口的对象来实现OnDataChangeListener方法public void setOnDataChangeListener(OnDataChangeListener dataChangeListener) {mDataChangeListener = dataChangeListener;}public interface OnDataChangeListener {void onDataChange(String data);}
}
  • mDataChangeListener是一个接口引用,用于存储对某个实现了OnDataChangeListener接口的对象的引用。
  • setOnDataChangeListener(OnDataChangeListener)方法允许外部对象(如ExampleFragment2)注册自己为观察者,让MainActivity能够在数据变化时通知它。
  • onClick4(View view)方法中调用mDataChangeListener.onDataChange()方法,这表示数据发生了变化,通知所有注册的观察者。

存储回调对象:在实际使用中,mDataChangeListener变量用于保存对某个对象(通常是匿名内部类或具体实现类)的引用,该对象提供了 onDataChange(String data) 方法的实现。这样,当数据发生变化时,我们可以通过这个变量来调用对应的实现,以通知数据变化。

  1. ExampleFragment2作为观察者
//其他方法省略
public class ExampleFragment2 extends Fragment {@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);tv1 = view.findViewById(R.id.tv1);((MainActivity) getActivity()).setOnDataChangeListener(new MainActivity.OnDataChangeListener() {@Overridepublic void onDataChange(String data) {if (!TextUtils.isEmpty(data)) {tv1.setText(data);}}});}
}
  • onViewCreated()方法中,ExampleFragment2注册了自己为MainActivity的观察者
  • 通过调用setOnDataChangeListener()方法,ExampleFragment2传入了一个匿名内部类,该类实现了OnDataChangeListener接口
  • 一旦MainActivity中调用onClick4(View view)方法,ExampleFragment2onDataChange(String data)方法被调用,从而更新界面(tv1.setText(data)

二、Fragment向Activity通信

2.1 通过getActivity

getActivity() 方法

返回当前 Fragment 正在附着的 Activity。它的返回类型是 Activity,如果 Fragment 尚未附着到 Activity,则返回 null

这样我们就可以通过附着的 Activity调用它的方法,更新Activity的UI或者传递数据‘

  1. Activity中使用
public class MainActivity extends AppCompatActivity {private TextView tv1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv1 = findViewById(R.id.tv1);//省略了该碎片的注册}public void setReceive(String data) {tv1.setText(data);}
  1. **在Fragment中使用getActivity**传递数据
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);btn = view.findViewById(R.id.btn_pass_data1);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//强制类型转换为 MainActivity((MainActivity) getActivity()).setReceive("这是我从Fragment里传递过来的数据");}});
}

2.2 通过接口

依然是观察者模式

image-20240727152811499

  1. ExampleFragment2作为被观察者
public class ExampleFragment2 extends Fragment {private Button btn2;  @Override  public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {  super.onViewCreated(view, savedInstanceState);   btn2 = view.findViewById(R.id.btn_pass_data2);  btn2.setOnClickListener(new View.OnClickListener() {  @Override  public void onClick(View v) {  // 判断是否设置了数据变化监听器  if (mFragmentDataChangeListener != null) {  // 如果设置了,则调用监听器的onFragmentDataChange方法,并传递数据  mFragmentDataChangeListener.onFragmentDataChange("这是我从Fragment里通过接口方法传递过来的数据");  }  }  });  }  // 定义一个接口,用于Fragment向Activity传递数据时的回调  // 这是一种观察者模式的实现方式  public interface OnFragmentDataChangeListener {  // 定义一个方法,当Fragment中的数据发生变化时,Activity可以通过此方法接收数据  void onFragmentDataChange(String data);  }  // 定义一个私有变量,用于存储实现了OnFragmentDataChangeListener接口的监听器  // 这个监听器通常由Activity实现并在Fragment与Activity关联时设置  private OnFragmentDataChangeListener mFragmentDataChangeListener;  // 提供一个公开的方法,允许外部(如Activity)设置数据变化监听器  // 这样Fragment就可以在需要时通知Activity数据已经发生变化  public void setFragmentDataChangeListener(OnFragmentDataChangeListener fragmentDataChangeListener) {  this.mFragmentDataChangeListener = fragmentDataChangeListener;  }  
}
  1. MainActivity作为观察者
public class MainActivity extends AppCompatActivity {private TextView tv1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tv1 = findViewById(R.id.tv1);//第二个fragment动态注册的if (savedInstanceState == null) {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();ExampleFragment2 fragment2 = new ExampleFragment2("这是我从碎片MainActivity传递的数据");fragmentTransaction.add(R.id.fragment_container2, fragment2);fragmentTransaction.commitNow();}// 获取FragmentManager,并尝试找到已经添加到指定容器的Fragment  FragmentManager fragmentManager = getSupportFragmentManager();  Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container2);  // 如果找到了Fragment,并且它确实是ExampleFragment2的实例,则设置数据变化监听器 if (fragment != null && fragment instanceof ExampleFragment2) {  // 将MainActivity作为监听器,监听来自Fragment的数据变化  ((ExampleFragment2) fragment).setFragmentDataChangeListener(new ExampleFragment2.OnFragmentDataChangeListener() {  // 当Fragment中的数据发生变化时,此方法会被调用  @Override  public void onFragmentDataChange(String data) {  // 更新TextView的文本为Fragment传递过来的数据  tv1.setText(data);  }});}}
}

由于 Fragment 的添加和视图的渲染是异步的,所以这里可能为空,需要如下操作:

  • if (fragment != null) 防止空指针异常,确保在尝试访问或操作 Fragment 之前,它已经被正确加载和初始化。
  • 还要使用commitNow()提交事务 ,fragment 在接下来的 findFragmentById() 调用中才有可能不为 null

三、Fragment之间传递数据

通过Activity中转

由于Activity是各个Fragment的承载者,所以可以作为中间桥梁为各个Fragment转递数据。

Fragment中可以通过getActivity()得到Activity对象。
Activity中可以通过findFragmentByld或者findFragmentByTag找到指定的Fragment,或者Fragment作为
Activity的成员变量直接使用。

所以,一个Fragment先拿到其Activity对象,再通过这个Activity找到指定的Fragment对象,然后调用其方法,从而传递数据

image-20240727155054917

image-20240727163104409

我这里有两个碎片在MainActivity上放着,并且他们各自都有一个按钮和文本,按钮用来发送数据,文本用来接收显示数据

ExampleFragment1中按钮的点击事件

// 设置按钮的点击监听器
btn1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 获取当前活动的实例,并通过它的 FragmentManager 查找指定 ID 的 FragmentFragment fragment = ((MainActivity) getActivity()).getSupportFragmentManager().findFragmentById(R.id.fragment_container2);// 检查找到的 Fragment 是否为非空if (fragment != null) {// 如果 Fragment 不为空,将数据传递给它// 强制将 Fragment 转换为 ExampleFragment2 类型,并调用 setData 方法传递数据((ExampleFragment2) fragment).setData("这是我从碎片1传递来的数据");}}
});

ExampleFragment2中方法,用来让ExampleFragment1设置2中的文本

public void setData(String data) {if (tvReceiveData != null) {tvReceiveData.setText(data);}
}
    if (fragment != null) {// 如果 Fragment 不为空,将数据传递给它// 强制将 Fragment 转换为 ExampleFragment2 类型,并调用 setData 方法传递数据((ExampleFragment2) fragment).setData("这是我从碎片1传递来的数据");}
}

});


`ExampleFragment2`中方法,用来让`ExampleFragment1`设置2中的文本```java
public void setData(String data) {if (tvReceiveData != null) {tvReceiveData.setText(data);}
}

这样就实现了ExampleFragment1ExampleFragment2传递数据,2向1也是一样的



感谢您的阅读
如有错误烦请指正


参考:

  1. 35.5-Fragment之间数据传递1_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3270245.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

聊聊基于Alink库的主成分分析(PCA)

概述 主成分分析(Principal Component Analysis,PCA)是一种常用的数据降维和特征提取技术,用于将高维数据转换为低维的特征空间。其目标是通过线性变换将原始特征转化为一组新的互相无关的变量,这些新变量称为主成分&…

关于链表、顺序表、栈和队列的一些总结

关于链表、顺序表、栈和堆的一些总结 1.顺序表2.链表2.1 单向链表2.1 带哨兵位双向循环链表 3.栈4.队列 1.顺序表 2.链表 2.1 单向链表 2.1 带哨兵位双向循环链表 3.栈 4.队列

【Matlab】绘图时使用字母控制线型和颜色(内含多图对比示例)

概要 测试了英文字母a-z不同输入下线条的颜色和线型,供参考选择。 语法 plot(x, y, 颜色); 如 plot(x, y, b); 测试 以下测试设置线宽为1.5,代码 x 0: 0.01: 2*pi; y sin(x); plot(x, y, b, LineWidth, 1.5);修改时把 b 改成不同字母即可 ‘a’…

基于关联规则的分类算法(CBA) | 项集、频繁项集、关联规则 | arulesCBA库

基于关联规则的分类算法 目前使用较多且较为简洁的关联规则分类算法是基于关联规则的分类算法(Classification Based on Association, CBA),下面将从该算法的相关概念开始介绍。 这部分笔记参考论文:孙菡悦.基于多因素交互效应的…

Linux第五节课(权限02)

1、Linux下的用户分类 root:超级用户普通用户:通过root新建的用户,adduser root不受权限约束;普通用户受权限约束; Linux系统中,所有用户都需要有密码,无论是root还是其他,即便是…

MySQL内如何改变编码格式

查找数据库的编码格式&#xff1a; show variables like character%;具体内容时这些 在创建表时设定编码格式&#xff1a; create database <要创建的数据库的名字> charset utf8; 修改数据库默认编码&#xff1a; set character_set_databaseutf8mb4; character_…

大模型算法备案流程最详细说明【流程+附件】

文章目录 一、语料安全评估 二、黑盒测试 三、模型安全措施评估 四、性能评估 五、性能评估 六、安全性评估 七、可解释性评估 八、法律和合规性评估 九、应急管理措施 十、材料准备 十一、【线下流程】大模型备案线下详细步骤说明 十二、【线上流程】算法备案填报…

【二分查找 数论】2513. 最小化两个数组中的最大值

本文涉及知识 二分查找算法合集 质数、最大公约数、菲蜀定理 LeetCode2513. 最小化两个数组中的最大值 给你两个数组 arr1 和 arr2 &#xff0c;它们一开始都是空的。你需要往它们中添加正整数&#xff0c;使它们满足以下条件&#xff1a; arr1 包含 uniqueCnt1 个 互不相同…

栈和队列<数据结构 C版>

目录 栈&#xff08;Stack&#xff09; 栈的结构体 初始化 销毁 入栈 判空 出栈 取栈顶元素 获取栈个数 测试&#xff1a; 队列&#xff08;Queue&#xff09; 队列的结构体 单个结点 队列 初始化 销毁 入队列&#xff0c;队尾 判空 出队列&#xff0c;队头 …

贪心算法.

哈夫曼树 哈夫曼树&#xff08;Huffman Tree&#xff09;&#xff0c;又称为霍夫曼树或最优二叉树&#xff0c;是一种带权路径长度最短的二叉树&#xff0c;常用于数据压缩。 定义&#xff1a;给定N个权值作为N个叶子结点&#xff0c;构造一棵二叉树&#xff0c;若该树…

大话成像公众号文章阅读学习(一)

系列文章目录 文章目录 系列文章目录前言一、扫射拍摄二、索尼Alpha 9 III2.1. 视频果冻效应2.2 闪光灯同步速度2.3 其他功能 三 A9III 局限性总结 前言 大话成像是一个专注成像的公众号&#xff0c;文章都很好。 今天看的这篇是 特朗普遭枪击后“大片”出自它 文章地址 htt…

Python | Leetcode Python题解之第284题窥视迭代器

题目&#xff1a; 题解&#xff1a; class PeekingIterator:def __init__(self, iterator):self.iterator iteratorself._next iterator.next()self._hasNext iterator.hasNext()def peek(self):return self._nextdef next(self):ret self._nextself._hasNext self.itera…

SGLang 大模型推理框架 qwen2部署使用案例;openai接口调用、requests调用

参考: https://github.com/sgl-project/sglang 纯python写,号称比vllm、tensorRT还快 暂时支持模型 安装 可以pip、源码、docker安装,这里用的pip 注意flashinfer安装最新版,不然会可能出错误ImportError: cannot import name ‘top_k_top_p_sampling_from_probs’ fr…

万物互联,触手可及“2024南京智慧城市,物联网,大数据展会”

在金秋送爽的11月&#xff0c;南京这座历史悠久而又充满活力的城市&#xff0c;即将迎来一场科技盛宴——2024南京智慧城市、物联网、大数据展会。这不仅是一场技术的集会&#xff0c;更是未来生活蓝图的预览&#xff0c;它汇聚了全球顶尖的科技企业、创新者及行业精英&#xf…

1.2 单链表定义及操作实现(链式结构)

1.单链表定义 链式存储&#xff1a;用一组任意的存储单元存储线性表中的数据元素。用这种方法存储的线性 表简称线性链表。 为了正确表示结点间的逻辑关系&#xff0c;在存储每个结点值的同时&#xff0c;还必须存储指示其直接 后继结点的地址&#xff08;或位置&#xff09;…

04-Charles中的Map Remote和Map Local介绍

Charles提供了Map Remote和Map Local两个功能。 Map Remote是将指定的网络请求重定向到另一个网址。Map Local是将指定的网络请求重定向到本地文件。 一、Map Remote 假设代码中调用了接口A&#xff0c;但是接口A的响应结果不能满足需求&#xff1b;此时&#xff0c;有另一个…

第15周 Zookeeper分布式锁与变种多级缓存

Zookeeper **************************************************************

heic怎么转换成jpg?heic转jpg,分享6款图片格式转换器免费汇总!

众所周知&#xff0c;在与非苹果手机设备用户&#xff08;如安卓手机或Windows台式机用户&#xff09;分享照片之前&#xff0c;通常需要将iphone的heic格式转换为jpg。由于这些操作系统的旧版本不原生支持heic图片格式&#xff0c;因此需要额外的第三方工具来查看这些图像。因…

0727,学什么学,周六就应该休息!!!!!

周六就应该休息&#xff0c;一天就忙了两小时也不是我的错喵 目录 UDP的小总结 01&#xff1a;使用select实现一个基于UDP的一对一即时聊天程序。 1.0 复读机服务器和树洞客户端 2.0 byby不了一点的敬业服务器&#xff01;&#xff01;&#xff01; 今天到此为止&#x…

24暑假算法刷题 | Day22 | LeetCode 77. 组合,216. 组合总和 III,17. 电话号码的字母组合

目录 77. 组合题目描述题解 216. 组合总和 III题目描述题解 17. 电话号码的字母组合题目描述题解 77. 组合 点此跳转题目链接 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输…