掌握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、创…...
ssm115乐购游戏商城系统+vue
毕业生学历证明系统 设计与实现 内容摘要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统毕业生学历信息管理难…...
【可实战】被测需求理解(需求文档是啥样的、从哪些角度进行需求评审、需求分析需要分析出哪些内容、如何提高需求分析能力)
产品人员会产出一个需求文档,然后组织一个需求的宣讲。测试人员的任务就是在需求宣讲当中,分析需求有没有存在一些问题,然后在需求宣讲结束之后通过分析需求文档,分析里面的测试点并预估一个排期。 一、需求文档是什么样的&#x…...
伪类和伪元素的区别是什么?
一、两者的定义 1.伪类(pseudo-class)是一个以冒号作为前缀,被添加到一个选择器末尾的关键字,当你希望样式在特定状态才被呈现到指定的元素时,你可以往元素的选择器后面加上对应的伪类。 2.伪元素用于创建一些不在文档…...
gorm-sharding分表插件升级版
代码地址: GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别.解决了原生s…...
MoviePy(Python音视频开发)
音视频基础帧率、码率、分辨率视频格式H.264和H.265视频压缩算法 Moviepy常见剪辑类VideoFlieClipImageFlieClipColorClipTextClipCompositeVideoClipAudioFlieClipCompositeAudioClip 常见操作音视频的读入与导出截取音视频 音视频基础 帧率、码率、分辨率 体积(V…...
Spring中的FileCopyUtils:文件复制的利器与详解
1. 概述 在Spring框架中,FileCopyUtils是一个用于文件复制操作的实用工具类。它提供了一系列静态方法,简化了文件从输入流到输出流、从文件到文件等的复制过程。这些方法都基于NIO(New I/O)技术,提供了高效的文件复制…...
【操作系统】读者—写者问题python解析
一个数据问价或记录可以被多个进程共享,我们把只读该文件的进程称为“读者进程”,其他进程为“写者进程”。允许多个进程同时读一个共享对象,但不允许一个写者进程和其他写者进程或读者进程同时访问共享对象。即:保证一个写者进程…...
【driver5】调用堆栈函数,printk,动态打印,ftrace,proc,sysfs
文章目录 1.内核函数调用堆栈:4个函数2.printk:cat /proc/cmdline查看consolettyS03.动态打印:printk是全局的且只能设打印等级,动态打印可控制选择模块的打印,在内核配置打开CONFIG_DYNAMIC_DEBUG4.top&perf&…...
计算机毕业设计springboot基于vue电商抢购限时秒杀系统ch0h8
技术栈 ide工具:IDEA 或者eclipse 编程语言: java 数据库: mysql5.7以上版本 可选框架:ssmspringboot都有的 前端:vue.jsElementUI 详细技术:springbootSSMvueMYSQLMAVEN 数据库工具:Navicat/SQLyog都可以 开发工具 Ec…...
顺序表的实现(迈入数据结构的大门)(2)
目录 顺序表的头插(SLPushFront) 此时:我们有两个思路(数组移位) 顺序表的头删(学会思维的变换)(SLPopFront) 顺序表的尾插(SLPushBack) 有尾插就有尾删 既然头与尾部的插入与删除都有,那必然少不了指定位置的插入删除 查找…...
地坪漆东莞网站建设技术支持/辽宁网站建设
我们在有些开发时候可能会用到些头条的文章,,添加过程如下所示: 我们在前台遍历数据的时候可以这样, 然后在后台更新首页模版后在去看下首页,效果如下所示: 转载于:https://www.cnblogs.com/leigood/p/5301…...
网站建设包括什么/百度云网盘下载
大部分的数据分析师都或多或少掉入这样的陷阱:每天大部分的工作都花在查数上,干着干着变成了“查数菇”。看上去帮老板或其他同事查数据是数据分析师天经地义的任务,怎么会成为陷阱呢?我来给你分析分析:业务部门需求多…...
在什么网站上可以做免费广告/强化防疫指导
什么是Viewport 手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的…...
做网站运营好还是SEO好/网站登录入口
怎么设置legacy启动?现在新型电脑都是采用uefi gpt启动模式,以适应win8、win10这些新型操作系统,不过win7之前的系统大多不支持uefi,而是采用legacy启动模式,硬盘分区表是MBR,而不是GPT,如果要在…...
在电脑上做苗木网站/百度在线客服中心
给霍尼韦尔官方打电话咨询了下,发现两者区别不大,唯一的区别是400B可以和主机联动,也就是主机关的时候,400B也可以自动关闭,不需要手动去关闭电源,这样非常方便。 本来官方是只有400A的时候,但是…...
商业设计说明/杭州seo网站
题面描述了一种加密的方式,让coder按照要求解密~ 将字母分成三段,再将位置用数组储存~所谓的旋转其实就是右移~ #include"cstdio" #include"iostream" #include"cstring" using namespace std; int main() { int k1,k2,…...