掌握Android Fragment开发之魂:Fragment的深度解析(下)
在上一篇文章中,我们深入探讨了Fragment 通信,包含Fragment 向 Activity 传递数据、Activity 向 Fragment 传递数据、Fragment 之间的通信方式。感兴趣的朋友,请前往查阅: 掌握Android Fragment开发之魂:Fragment的深度解析(中) 。
在这篇文章中,我们将继续深入探讨 Android Fragment,包括以下几个核心主题:
-
DialogFragment 是什么
-
DialogFragment相比 Dialog的优势
-
DialogFragment 的使用方式
-
Fragment 在 Android 开发中的最佳实践
一、DialogFragment 的魅力所在
1、DialogFragment 是什么?
DialogFragment 是 Android 开发中用于创建和管理对话框的一个类,它是 Fragment 的一个子类,专门用于显示对话框界面。在 Android 中,对话框是一种浮动的 UI 元素,通常用于提供额外的信息或选项,而不会干扰用户当前的操作。
以下是 DialogFragment 的一些关键特点:
-
模态性:
DialogFragment通常以模态的形式出现,意味着用户必须与对话框交互(如确认或取消操作)才能返回到应用程序的其他部分。 -
生命周期:
DialogFragment拥有自己的生命周期,与宿主Activity的生命周期相互独立。它在onCreate方法中初始化,在onCreateView方法中创建视图,在onShow方法中显示,在onDismiss方法中关闭。 -
自定义视图:开发者可以在
onCreateView方法中定义自己的布局文件,从而实现高度自定义的对话框界面。 -
显示与隐藏:可以通过调用
show方法将DialogFragment显示在宿主Activity上,也可以调用dismiss方法将其隐藏。 -
主题和样式:可以为
DialogFragment设置不同的主题和样式,以适应不同的 UI 设计需求。 -
交互:
DialogFragment可以包含按钮、列表、文本框等 UI 组件,允许用户进行交互。 -
BackStack:当
DialogFragment被添加到FragmentTransaction时,可以选择是否将其添加到回栈(BackStack)中,这允许用户通过按返回键来导航。
2、DialogFragment相比 Dialog的优势
DialogFragment 相比于传统的 Dialog 有以下几个优势:
-
生命周期可控
DialogFragment
拥有自己的生命周期,能够更好地与Activity和Fragment的生命周期进行协同。当Activity被销毁时,与之关联的DialogFragment` 也会被销毁,这有助于避免内存泄漏。 -
UI更新
DialogFragment` 可以更容易地响应配置更改(如屏幕旋转),在这些情况下,对话框可以保持其状态,而不需要重新创建。
-
BackStack 管理
DialogFragment可以被添加到 Fragment 的回栈(BackStack)中,这意味着用户可以使用返回键来关闭对话框,提供了更好的用户体验。 -
样式和主题
DialogFragment允许开发者通过设置不同的主题和样式来自定义对话框的外观,这在传统的Dialog中实现起来可能更加困难。 -
兼容性
随着 Android 系统的更新,
DialogFragment能够更好地适应新的 UI 设计和交互模式,而传统的Dialog可能需要更多的工作来保持兼容性。 -
代码复用,解耦设计
DialogFragment允许开发者创建可复用的对话框模板,可以在不同的Activity中重复使用,而不需要为每个Activity编写相同的代码。 -
与 Fragment 协同
如果你的应用程序已经使用了
Fragment来管理 UI 的不同部分,使用DialogFragment可以保持代码的一致性,并且可以更容易地在Fragment之间共享数据。 -
动画和转场支持
DialogFragment` 支持自定义的进入和退出动画,这使得对话框的显示和隐藏可以有更丰富的视觉效果。
-
更清晰的代码结构
使用
DialogFragment可以使代码结构更加清晰,因为每个对话框都是一个独立的实体,拥有自己的逻辑和布局。 -
支持 Fragment 事务
DialogFragment` 可以作为 Fragment 事务的一部分进行管理,这使得在运行时添加、替换或删除对话框变得更加容易。
-
丰富的回调
DialogFragment 提供了更多的回调方法,如
onCreateDialog()、onResume()等。
总的来说,DialogFragment 提供了更好的生命周期管理、更灵活的 UI 更新、更丰富的自定义选项以及更好的用户体验,这些优势使其成为在 Android 应用中创建和管理对话框的首选方式。
3、DialogFragment 的使用方式
接下来,我们通过一个示例来演示 DialogFragment 的使用方式。
public class MyDialogFragment extends DialogFragment {@NonNull@Overridepublic Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());builder.setTitle("标题").setMessage("这是一个 DialogFragment").setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 处理确定按钮点击事件}}).setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// 处理取消按钮点击事件}});return builder.create();}
}
要显示该 DialogFragment,只需要在 Activity 中执行以下代码:
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 显示 DialogFragmentshowDialogFragment();}private void showDialogFragment() {MyDialogFragment dialogFragment = new MyDialogFragment();dialogFragment.show(getSupportFragmentManager(), "MyDialogFragment");}
}
在 MainActivity 中,我们首先实例化 MyDialogFragment。然后,调用 show() 方法并传入 FragmentManager 实例和一个可选的标签(用于标识该 DialogFragment)来显示该 DialogFragment。
show() 方法的完整签名如下:
public void show(@NonNull FragmentManager manager, @Nullable String tag)
manager: 用于管理 Fragment 的 FragmentManager 实例。tag: 可选的字符串标签,用于标识该 DialogFragment。如果你需要在将来获取该 DialogFragment 的实例,可以使用这个标签。
在上面的示例中,我们使用 getSupportFragmentManager() 获取 FragmentManager 实例,并将标签设置为 “MyDialogFragment”。
你还可以通过 DialogFragment 的其他方法来自定义对话框的样式和行为,例如:
setStyle(): 设置对话框的样式(默认、全屏等)。setCancelable(): 设置对话框是否可以通过点击外部区域或按下返回键来取消。setShowsDialog(): 控制是否显示对话框标题和按钮。
通过上述代码和扩展方法,你就可以灵活地创建和管理 DialogFragment 了。DialogFragment 不仅提供了标准的 Fragment 生命周期管理,还增强了对话框的可定制性,是展示模态界面的绝佳选择。
二、Fragment 在 Android 开发中的最佳实践
在 Android 应用程序开发中,合理使用 Fragment 可以带来诸多好处,提高代码的可维护性和用户体验。因此,掌握 Fragment 的最佳实践是非常有必要的。
1、保持 Fragment 精简
Fragment 被设计为可重用的界面构建块,因此应该保持其职责单一、逻辑精简。
将过多的业务逻辑耦合到 Fragment 中会增加其复杂性,影响可维护性。
相反,应该将业务逻辑分离到其他层次,如 ViewModel 或 Repository,而让 Fragment 专注于界面呈现和用户交互。
2、高度解耦设计
遵循单一责任原则,Fragment 应该与其他组件(如 Activity、ViewModel 等)高度解耦。
这种解耦设计可以最大限度地提高代码的可复用性和可测试性。
例如,可以通过定义接口或使用依赖注入等方式来降低 Fragment 与其他组件的耦合度。
3、避免过度嵌套
虽然 Fragment 可以嵌套,但过度嵌套会导致界面层次过深,增加复杂性和性能开销。
因此,应该权衡利弊,尽量保持 Fragment 嵌套的层次浅一些。
如果确实需要嵌套,可以考虑使用 ViewPager 等容器来管理多个 Fragment。
4、注意生命周期管理
Fragment 具有自己的生命周期,与其宿主 Activity 的生命周期存在一定的联系。
在编写 Fragment 代码时,需要特别注意生命周期方法的调用顺序和时机,避免出现内存泄漏或数据丢失等问题。
同时,也要注意在适当的生命周期方法中执行相应的操作,如数据加载、视图绑定等。
public class MyFragment extends Fragment {@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 初始化操作}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {// 加载布局return inflater.inflate(R.layout.fragment_my, container, false);}@Overridepublic void onViewCreated(View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);// 初始化视图组件}@Overridepublic void onDestroyView() {super.onDestroyView();// 清理操作,如取消动画、移除监听器等}@Overridepublic void onDestroy() {super.onDestroy();// 最终清理操作}
}
5、利用 FragmentManager 的力量
FragmentManager 是管理 Fragment 生命周期和事务的核心组件。
掌握 FragmentManager 的使用技巧,如 add()、replace()、remove()、addToBackStack() 等方法,可以更好地控制 Fragment 的行为,可以确保 UI 更新的一致性。
同时,也要注意合理利用回退栈,为用户提供流畅的导航体验。
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, new MyFragment()); // 替换 Fragment
transaction.addToBackStack(null); // 添加到回栈
transaction.commit(); // 提交事务
6、避免在 Fragment 中进行长时间运行的操作
长时间运行的操作应该在后台线程中执行,以避免阻塞主线程。
new AsyncTask<Void, Void, Void>() {@Overrideprotected Void doInBackground(Void... voids) {// 长时间运行的操作return null;}@Overrideprotected void onPostExecute(Void aVoid) {// 更新 UI}
}.execute();
7、使用 setUserVisibleHint 来优化性能
这个方法可以帮助了解 Fragment 是否对用户可见,从而优化性能。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {super.setUserVisibleHint(isVisibleToUser);if (isVisibleToUser) {// 当 Fragment 对用户可见时执行的操作}
}
8、正确处理 Fragment 回栈
当用户按下返回键时,确保正确处理 Fragment 回栈,提供一致的用户体验。
@Override
public void onBackStackChanged() {super.onBackStackChanged();if (getFragmentManager().getBackStackEntryCount() == 0) {// 处理回栈为空的情况,如退出 Activity}
}
9、使用 Fragment 的 newInstance 方法
这是一种创建 Fragment 实例的推荐方式,它使得传递参数变得更加容易。
复制
public static MyFragment newInstance() {MyFragment fragment = new MyFragment();Bundle args = new Bundle();// 向 args 中添加参数fragment.setArguments(args);return fragment;
}
10、避免内存泄漏
确保在 onDestroy 或 onDestroyView 中清理资源,如移除监听器、取消动画等。
@Override
public void onDestroyView() {super.onDestroyView();if (someListener != null) {someView.removeOnClickListener(someListener);someListener = null;}
}
11、使用 LoaderManager 进行数据加载
使用 LoaderManager 可以帮助你管理后台数据加载,并在 Fragment 重新创建时恢复加载状态。
@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);getLoaderManager().initLoader(0, null, this);
}@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {// 创建并返回数据加载器
}@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {// 数据加载完成,更新 UI
}@Override
public void onLoaderReset(Loader<Cursor> loader) {// 数据加载器被重置,清理数据
}
通过上述最佳实践,我们能够更高效地管理 Fragment,提升应用的稳定性和性能,可以帮助你创建更加健壮且易于维护的 Android 应用。
相关文章:
掌握Android Fragment开发之魂:Fragment的深度解析(下)
在上一篇文章中,我们深入探讨了Fragment 通信,包含Fragment 向 Activity 传递数据、Activity 向 Fragment 传递数据、Fragment 之间的通信方式。感兴趣的朋友,请前往查阅: 掌握Android Fragment开发之魂:Fragment的深度…...
小巧简单实用的Linux端口转发工具Rinetd
Linux下实现端口转发有很多种方法,尤其是在可以联网的情况下,更是容易。最近在资源受限的定制系统中,找到一个方便离线安装和使用的端口转发工具Rinetd,安装包仅几十K,而且有很多版本的Linux发行系统的支持。 1、安装…...
HackBar 新手使用教程(入门)
啥是Hackbar? Hackbar是一个Firefox 的插件,它的功能类似于地址栏,但是它里面的数据不受服务器的相应触发的重定向等其它变化的影响。 有网址的载入于访问,联合查询,各种编码,数据加密功能。 这个Hackbar可以帮助你在测试SQL注入,XSS漏洞和网站的安全性,主要是帮助…...
<Linux> 权限
目录 权限人员相对于文件来说的分类更改权限文件的拥有者与所属组umask粘滞位 权限 权限是操作系统用来限制对资源访问的机制,权限一般分为读、写、执行。系统中的每个文件都拥有特定的权限、所属用户及所属组,通过这样的机制来限制哪些用户、哪些组可以…...
Nacos Docker 快速部署----解决nacos鉴权漏洞问题
Nacos Docker 快速部署 1. 说明 1.1 官方文档 官方地址 https://nacos.io/zh-cn/docs/v2/quickstart/quick-start.html docker启动文件的gitlhub地址 https://github.com/nacos-group/nacos-docker.git 问题: 缺少部分必要配置与说明 1.2 部署最新版本Nacos&…...
存储或读取时转换JSON数据
一、 数据库类型 二、使用Hutool工具 存储时将数据转换为JSON数据 获取时将JSON数据转换为对象 发现问题: 原本数据对象是Address 和 Firend但是转换完成后数据变成了JSONArray和JSONObject 三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器 package …...
Spring Data JPA的作用和用法
Spring Data JPA 是 Spring 框架的一个模块,它提供了一种数据访问抽象,允许以一种声明式和简洁的方式来处理数据库操作。它基于 Java Persistence API (JPA),是一个行业标准的 ORM(对象关系映射)规范,用于将…...
【go项目01_学习记录08】
学习记录 1 模板文件1.1 articlesStoreHandler() 使用模板文件1.2 统一模板 1 模板文件 重构 articlesCreateHandler() 和 articlesStoreHandler() 函数,将 HTML 抽离并放置于独立的模板文件中。 1.1 articlesStoreHandler() 使用模板文件 . . . func articlesSt…...
Java中的线程
一、创建线程的几种方式? ① 通过继承Thread类并重写run方法 ,实现简单但不可以继承其他类 Thread底层也是实现了Runnable接口,重写的是run而不是start方法 ②实现Runnable接口并重写run方法, 避免了单继承的局限性ÿ…...
顺序表的实现(迈入数据结构的大门)(完整代码)
seqlist.h #pragma once typedef int SLDataType;#include<stdio.h> #include<stdlib.h> #include<assert.h>typedef struct SeqList {SLDataType* a;int size; // 有效数据个数int capacity; // 空间容量 }SL;//初始化和销毁 void SLInit(SL* ps); void SL…...
neo4j-5.11.0安装APOC插件or配置允许使用过程的权限
在已经安装好neo4j和jdk的情况下安装apoc组件,之前使用neo4j-community-4.4.30,可以找到配置apoc-4.4.0.22-all.jar,但是高版本neo4j对应没有apoc-X.X.X-all.jar。解决如下所示: 1.安装好JDK与neo4j 已经安装对应版本的JDK 17.0…...
mybatis 中 #{}和 ${}的区别是什么?
在 MyBatis 中,#{} 和 ${} 是两种用于参数替换的语法,但它们之间存在一些重要的区别,主要体现在安全性、预编译和动态 SQL 上。 安全性: #{}:这是预编译处理,MyBatis 会为传入的参数生成 PreparedStatement…...
深入解析C#中的接口设计原则
深入解析C#中的接口设计原则 目录 深入解析C#中的接口设计原则 一、接口设计的SOLID原则 二、接口设计的最佳实践 三、接口设计的高级技术 四、结论 接口在面向对象编程中扮演着至关重要的角色。它们是定义行为契约的一种方式,允许实现者提供这些行为的具体实现…...
106短信群发平台在金融和法务行业的应用分析
一、金融行业应用 1.客户通知与提醒:银行、证券、保险等金融机构经常需要向客户发送各类通知和提醒,如账户余额变动、交易确认、扣费通知、理财产品到期提醒等。106短信群发平台可以快速、准确地将这些信息发送到客户的手机上,确保客户及时获…...
Spring AOP(2)
目录 Spring AOP详解 PointCut 切面优先级Order 切点表达式 execution表达式 切点表达式示例 annotation 自定义注解MyAspect 切面类 添加自定义注解 Spring AOP详解 PointCut 上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重…...
Spring-依赖注入的处理过程
前置知识 1 入口 DefaultListableBeanFactory#resolveDependency 2 每个依赖都有对应的DependencyDescriptor 3 自定绑定候选对象处理器AutowireCapableBeanFactory 注入处理 我们可以看到接口AutowireCapableBeanFactory中有两个方法。 第一个是单个注入: Null…...
2.用python爬取的保存在text文件中的格式为MP4的视频url
文章目录 一、url的保存格式二、MP4视频获取 一、url的保存格式 爬取的视频名字和url保存在text文件中,每一个视频都是一个单独的text,其中text的文件名就是视频的名字,text内容是视频的下载url,并且所有的text都保存在同一个文件…...
Java基于B/S医院绩效考核管理平台系统源码java+springboot+MySQL医院智慧绩效管理系统源码
Java基于B/S医院绩效考核管理平台系统源码javaspringbootMySQL医院智慧绩效管理系统源码 医院绩效考核系统是一个关键的管理工具,旨在评估和优化医院内部各部门、科室和员工的绩效。一个有效的绩效考核系统不仅能帮助医院实现其战略目标,还能提升医疗服…...
UE 蓝图堆栈调试
蓝图打断点后如果想查看断点前的执行逻辑,Tools→Debug→BlueprintDebugger 然后打断点运行,执行顺序是从下往上...
UE4_摄像机_使用摄像机的技巧
学习笔记,不喜勿喷!祝愿生活越来越好! 知识点: a.相机跟随。 b.相机抖动。 c.摄像机移动 d.四元数插值(保证正确旋转方向)。 e.相机注视跟踪。 1、新建关卡序列,并给小车添加动画。 2、创…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
