一、activity与Fragment的通信有哪些?

        使用接口进行通信的逻辑与代码示例

        使用接口通信的核心是解耦,通过定义一个接口作为通信契约,让 Fragment 不依赖于具体的 Activity 类型。

1. 定义通信接口(在 Fragment 内)

首先,在 Fragment 内部定义一个公共接口。这个接口就像一份协议,规定了 Fragment 想要传递给 Activity 的信息类型和方法。

// MyFragment.java
public class MyFragment extends Fragment {// 定义通信接口public interface OnMessageSendListener {void onMessageSent(String message);}private OnMessageSendListener listener;// ... 其他 Fragment 生命周期方法@Overridepublic void onAttach(@NonNull Context context) {super.onAttach(context);// 检查宿主 Activity 是否实现了接口if (context instanceof OnMessageSendListener) {listener = (OnMessageSendListener) context;} else {// 如果没有实现,抛出异常,提醒开发者throw new RuntimeException(context.toString() + " must implement OnMessageSendListener");}}// Fragment 内部触发事件的方法private void triggerCommunication() {if (listener != null) {// 调用接口方法,传递数据listener.onMessageSent("Hello from Fragment!");}}
}
2. Activity 实现接口并处理数据

然后,你的 Activity 必须实现这个接口。这就像在说:“好的,我愿意遵守这份契约,并且知道如何处理来自 Fragment 的数据。”

// MyActivity.java
public class MyActivity extends AppCompatActivity implements MyFragment.OnMessageSendListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 假设这里将 MyFragment 添加到了 ActivitygetSupportFragmentManager().beginTransaction().add(R.id.fragment_container, new MyFragment()).commit();}// 实现接口中定义的方法@Overridepublic void onMessageSent(String message) {// 在 Activity 中处理从 Fragment 接收到的数据Toast.makeText(this, "收到来自 Fragment 的消息: " + message, Toast.LENGTH_SHORT).show();}
}

逻辑总结: 这个过程非常清晰:Fragment 不关心它的宿主是谁,它只知道需要一个实现了 OnMessageSendListener 接口的对象。只要 Activity 遵守了这个约定,通信就能安全地进行。这种方式彻底解耦了 Fragment 和 Activity,提高了 Fragment 的可复用性。

        使用 ViewModel 进行通信的逻辑与代码示例

使用 ViewModel 进行通信的核心是数据驱动。Activity 和 Fragment 不再直接交互,而是通过一个共享的 ViewModel 实例作为数据中心,来同步数据。

1. 创建共享的 ViewModel

首先,创建一个继承自 ViewModel 的类,并用 MutableLiveData 来封装你需要共享的数据。

// SharedViewModel.java
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;public class SharedViewModel extends ViewModel {// MutableLiveData 用于在 ViewModel 内部修改数据private final MutableLiveData<String> selectedItem = new MutableLiveData<>();// 提供一个公开方法,供外部调用以更新数据public void selectItem(String item) {selectedItem.setValue(item);}// 提供一个不可变的 LiveData 实例供外部观察public LiveData<String> getSelectedItem() {return selectedItem;}
}
2. Fragment A(数据发送方)

在发送数据的 Fragment 中,通过其宿主 Activity 的范围(by activityViewModels()ViewModelProvider)获取 ViewModel 的实例,然后调用其方法来更新数据。

// FragmentA.java
public class FragmentA extends Fragment {// 获取共享的 ViewModel 实例private SharedViewModel sharedViewModel;@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 使用 ViewModelProvider 获取同一个实例sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_a, container, false);Button button = view.findViewById(R.id.send_button);button.setOnClickListener(v -> {// 当按钮被点击时,更新 ViewModel 中的数据sharedViewModel.selectItem("Data from Fragment A");});return view;}
}
3. Fragment B(数据接收方)

在接收数据的 Fragment 中,也通过同样的方式获取 ViewModel 的实例,然后观察observeLiveData 的变化。

// FragmentB.java
public class FragmentB extends Fragment {private SharedViewModel sharedViewModel;private TextView textView;@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_b, container, false);textView = view.findViewById(R.id.received_data_text_view);// 观察 ViewModel 中的数据变化sharedViewModel.getSelectedItem().observe(getViewLifecycleOwner(), item -> {// 当数据发生变化时,更新 UItextView.setText(item);});return view;}
}

        逻辑总结: 这个过程的核心是数据流。Fragment A 只负责更新 ViewModel 中的数据,Fragment B 和 Activity 只负责观察这些数据。它们之间没有直接引用。这种方式不仅彻底解耦了组件,还利用了 LiveData 的生命周期感知特性,自动处理了数据在屏幕旋转等配置变化时的持久化,有效防止了内存泄漏。它代表了现代 Android 开发中组件通信的最新趋势和最佳实践。

二、String类与List,Set,Map类

StringStringBuilderStringBuffer 三者作用、意义和区别。

        String 是最基础的字符串类,但它最大的特点是不可变性。这意味着一旦创建,它的值就无法改变。任何对 String 的修改操作,比如拼接,都会在内存中创建一个全新的 String 对象,而旧的对象则会被回收。因此,String 适用于那些不需要频繁修改的场景,它的不可变性也保证了线程安全,使其成为一个可靠的数据类型。然而,如果需要进行大量的字符串操作,尤其是在循环中,频繁创建新对象的开销会严重影响程序性能。

        为了解决 String 的性能问题,Java 引入了 StringBuilderStringBuffer。这两者都属于可变的字符串,它们在内部维护一个动态的字符数组,可以直接在原有对象上进行修改,而无需创建新的对象。这使得它们在进行字符串拼接、插入等操作时,效率远高于 String。其中,StringBuilder 的性能最高,因为它没有线程同步(synchronized)的开销,这使得它在单线程环境下成为处理字符串修改的首选工具。

        StringBufferStringBuilder 的功能几乎完全相同,但关键区别在于线程安全性StringBuffer 的所有方法都是线程同步的,这意味着在多线程环境中,它可以确保同一时间只有一个线程能访问它,从而避免了数据不一致的问题。然而,这种同步机制会带来额外的性能开销,所以在单线程环境下,使用 StringBuffer 是不必要的,会比 StringBuilder 慢。因此,在选择时,应根据项目的具体需求来决定:单线程用 StringBuilder,多线程用 StringBuffer,而 String 则用于处理不需要修改的简单字符串。

ListSetMap 是 Java 集合框架中最基础也是最重要的三种接口,它们都用于存储对象,但各自有独特的存储方式、行为和适用场景。理解它们的区别,是高效编程的关键。

List(列表)

        List 是一种有序、可重复的集合。你可以把它想象成一个数组,每个元素都有一个对应的索引,因此你可以通过索引来精确地访问、添加或删除元素。由于它允许重复元素,你可以多次添加同一个对象。在实际应用中,当你需要一个元素的顺序很重要,或者需要存储重复数据时,List 是你的首选。常见的实现类有 ArrayListLinkedList,前者基于数组,随机访问速度快;后者基于链表,插入和删除操作更高效。

Set(集合

        Set 是一种无序、不可重复的集合。它的行为更像一个数学意义上的集合,所有元素都是唯一的。当你试图向一个 Set 中添加一个已经存在的元素时,添加操作会失败。正因为这种独一无二的特性,Set 非常适合用来去重。例如,如果你需要统计一篇文章中不重复的单词数量,Set 就能轻松胜任。常见的实现类有 HashSetTreeSetHashSet 提供了最快的查找速度,而 TreeSet 则会保持元素的排序。

Map(映射)

        Map 是一种键值对的集合。它存储的不是单个元素,而是由“键(Key)”和“值(Value)”组成的配对。每个键都是唯一的,并且与一个值相关联。你可以通过键来快速查找、更新或删除对应的值,就像查字典一样。Map 非常适合用于存储需要通过某种唯一标识来检索的数据,比如一个用户的 ID 对应其个人信息,或者一个学生的学号对应其成绩。常见的实现类有 HashMapTreeMapHashMap 提供了无序的快速存取,而 TreeMap 则会按键的自然顺序进行排序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/95015.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/95015.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/95015.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法】78.子集--通俗讲解

通俗易懂讲解“子集”算法题目 一、题目是啥?一句话说清 给你一个不含重复元素的整数数组,返回所有可能的子集(包括空集和它本身)。 示例: 输入:nums = [1,2,3] 输出:[[], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]] 二、解题核心 使用回溯法(递归)或位运算来…

Cherrystudio的搭建和使用

1、下载和安装 Cherry Studio 官方网站 - 全能的 AI 助手 2、配置LLM 3、聊天助手 3.1 添加和编辑助手 3.2 选择LLM 3.3 对话聊天 4、配置MCP 4.1 安装MCP执行插件 4.2 安装 node和npm Node.js — Download Node.js npm -v 10.9.3 node -v v22…

基于Matlab结合肤色检测与卷积神经网络的人脸识别方法研究

近年来&#xff0c;随着人工智能与计算机视觉技术的发展&#xff0c;人脸识别在人机交互、安防监控、身份认证等领域得到了广泛应用。本文提出了一种基于 MATLAB 平台&#xff0c;结合 肤色检测与卷积神经网络&#xff08;CNN&#xff09; 的人脸识别方法。该方法首先利用肤色模…

在八月点燃AI智慧之火:CSDN创作之星挑战赛开启灵感盛宴

在八月点燃AI智慧之火&#xff1a;CSDN创作之星挑战赛开启灵感盛宴八月骄阳似火&#xff0c;智能时代的技术热情同样炽热。在这个充满创新活力的季节&#xff0c;「AIcoding八月创作之星挑战赛」正式拉开帷幕&#xff0c;为CSDN的创作者们打造一个展示才华、碰撞灵感的专业舞台…

解密 Vue 3 shallowRef:浅层响应式 vs 深度响应式的性能对决

&#x1f4d6; 概述 shallowRef() 是 Vue 3 中的一个组合式 API 函数&#xff0c;用于创建浅层响应式引用。与 ref() 不同&#xff0c;shallowRef() 只在其 .value 被直接替换时触发响应式更新&#xff0c;不会深度监听对象内部属性的变化。 &#x1f3af; 基本概念 什么是 sh…

Linux进程间通信(IPC)深入解析

Linux进程间通信&#xff08;IPC&#xff09;深入解析 1 概述 Linux 进程间通信 (Inter-Process Communication, IPC) 是不同进程之间交换数据与同步操作的机制。现代 Linux 内核提供了多种 IPC 方式&#xff0c;从传统的管道和 System V IPC 到现代的套接字和 D-Bus&#xff0…

TensorFlow-GPU版本安装

前言&#xff1a; &#xff08;1&#xff09;因项目需求&#xff0c;需要安装TensorFlow-GPU版本&#xff0c;故本文在此记录安装过程。 &#xff08;2&#xff09;有注释&#xff0c;优先看注释 &#xff08;3&#xff09;本文所使用的GPU为NVIDIA GeForce RTX 5080 Laptop GP…

Elasticsearch 索引字段删除,除了 Reindex 重建索引还有没有别的解决方案?

unsetunset1、问题来源unsetunset在生产环境维护 Elasticsearch 集群的过程中&#xff0c;经常会遇到这样的场景&#xff1a;业务需求变更导致某些字段不再使用&#xff0c;或者早期设计时添加了一些冗余字段&#xff0c;现在需要清理掉。最近球友在公司的一个项目中就遇到了这…

Ubuntu虚拟机磁盘空间扩展指南

这是一份详细且易于理解的 Ubuntu 虚拟机磁盘空间扩展指南。本指南涵盖了两种主流虚拟机软件&#xff08;VirtualBox 和 VMware&#xff09;的操作步骤&#xff0c;并分为 “扩展虚拟磁盘” 和 “在 Ubuntu 内部分配新空间” 两大部分。重要提示&#xff1a;在进行任何磁盘操作…

教程1:用vscode->ptvsd-创建和调试一个UI(python)-转载官方翻译(有修正)

vscode用python开发maya联动调试设置 3dsMax Python开发环境搭建 3文联动之debugpy调试max‘python. 3文联动之socket插槽注入max‘python 本教程是max主动接收创建代码的方式&#xff08;预先运行界面&#xff0c;通过按钮主动读取py脚本&#xff0c;执行断点&#xff09;&…

龙迅#LT7621GX适用于两路HDMI2.1/DP1.4A转HDMI2.1混切应用,分辨率高达8K60HZ!

1. 描述LT7621GX是一款高性能两路HDMI2.1/DP1.4转HDMI2.1混合开关芯片&#xff0c;用于显示应用。 HDCP RX作为HDCP中继器的上游&#xff0c;可以与其他芯片的HDCP TX配合&#xff0c;实现中继器功能。 对于HDMI2.1输入&#xff0c;LT7621GX可以配置为3/4通道。自适应均衡使其适…

【Ruoyi 解密 - 12. JDK17的新特性】------ 从Java 8 到 Java 17:向Scala看齐的“简洁革命”,同宗JVM下的效率狂飙

从Java 8到Java 17&#xff1a;抄作业Scala&#xff1f;JVM同宗下的Ruoyi开发效率狂飙&#xff01; 上一篇我们聊到JDK 17对Python的柔性借鉴&#xff0c;可深入用下来才发现——这哪够&#xff01;对Ruoyi开发者来说&#xff0c;JDK 17真正的“王炸”&#xff0c;是把同根JVM的…

大模型 “轻量化” 之战:从千亿参数到端侧部署,AI 如何走进消费电子?

一、大模型 “轻量化” 的行业背景在 AI 技术蓬勃发展的当下&#xff0c;大模型已然成为行业焦点。从 GPT-4 突破万亿级参数量&#xff0c;到 DeepSeek-R1 迈向千亿参数规模&#xff0c;大模型的参数扩张趋势显著。然而&#xff0c;这种规模的增长也带来了诸多挑战。以 GPT-4 为…

香港电讯与Microsoft香港推出新世代“Teams Phone” 解决方案

香港电讯成为香港首家提供 “Microsoft Operator Connect”的本地电讯营运商1 香港电讯&#xff08;股份代号&#xff1a;6823&#xff09;【香港 • 2025年2月11日】 – 香港电讯宣布与 Microsoft 香港合作推出 “Operator Connect”&#xff0c;成为全港首家为企业客户提供全…

PlantUML描述《分析模式》第3章观察和测量(2)

lantUML描述《分析模式》第2章“当责”&#xff08;1&#xff09; PlantUML描述《分析模式》第2章“当责”&#xff08;2&#xff09; PlantUML描述《分析模式》第3章观察和测量&#xff08;1&#xff09; 原图3.8 EA绘制 图3.8 递归关系用于记录证据和评估。 PlantUML sta…

轮廓周长,面积,外界圆,外界矩形近似轮廓和模板匹配和argparse模块实现代码参数的动态配置

目录 一.轮廓操作 1.轮廓特征的引入与筛选 2.轮廓排序和精准定位 3.外接圆与外接矩形的计算与绘制 二.轮廓近似 1.轮廓近似的基本概念 2.轮廓近似的实现方法和核心步骤 3. 近似精度参数的设定逻辑 4.轮廓定位方法 三.模板匹配 1.模板匹配技术原理与实现流程 2.技术要…

【第三方网站测评:会话管理漏洞的测试与加固】

会话管理是Web应用安全的用于在无状态的HTTP协议上维持用户状态。漏洞主要源于会话令牌(Session Token)的生成、传输、验证和销毁过程中的缺陷。攻击者利用这些缺陷可劫持用户会话,未经授权访问敏感数据或执行特权操作,属于OWASP TOP 10中身份验证失效的高频风险。 会话管…

理想汽车智驾方案介绍专题 3 MoE+Sparse Attention 高效结构解析

一、前言 【理想汽车智驾方案介绍专题 -1】端到端VLM 方案介绍 【理想汽车智驾方案介绍专题 -2】MindVLA 方案详解 在上述两篇系列帖子中&#xff0c;笔者已对理想汽车 VLM 和 VLA 方案的框架进行了全面介绍&#xff0c;但对于其中的前沿技术仅做了初步探讨&#xff0c;未进…

如何将yolo训练图像数据库的某个分类的图像取出来

COCO 数据集 - Ultralytics YOLO 文档 比如我只想从数据集中取手机的图像&#xff0c;来用于我的训练&#xff0c;懒得自己一张一张标注&#xff0c;方法如下 # -*- coding: utf-8 -*- import json import os import shutil from pathlib import Path from tqdm import tqdm i…

【WPF】WPF 自定义控件实战:从零打造一个可复用的 StatusIconTextButton (含避坑指南)

&#x1f527; WPF 自定义控件实战&#xff1a;从零打造一个可复用的 StatusIconTextButton&#xff08;含避坑指南&#xff09;发布于&#xff1a;2025年8月29日 标签&#xff1a;WPF、C#、自定义控件、MVVM、Generic.xaml、属性绑定、TemplateBinding&#x1f4cc; 引言 在 W…