掌握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 的一些关键特点:

  1. 模态性DialogFragment 通常以模态的形式出现,意味着用户必须与对话框交互(如确认或取消操作)才能返回到应用程序的其他部分。

  2. 生命周期DialogFragment 拥有自己的生命周期,与宿主 Activity 的生命周期相互独立。它在 onCreate 方法中初始化,在 onCreateView 方法中创建视图,在 onShow 方法中显示,在 onDismiss 方法中关闭。

  3. 自定义视图:开发者可以在 onCreateView 方法中定义自己的布局文件,从而实现高度自定义的对话框界面。

  4. 显示与隐藏:可以通过调用 show 方法将 DialogFragment 显示在宿主 Activity 上,也可以调用 dismiss 方法将其隐藏。

  5. 主题和样式:可以为 DialogFragment 设置不同的主题和样式,以适应不同的 UI 设计需求。

  6. 交互DialogFragment 可以包含按钮、列表、文本框等 UI 组件,允许用户进行交互。

  7. BackStack:当 DialogFragment 被添加到 FragmentTransaction 时,可以选择是否将其添加到回栈(BackStack)中,这允许用户通过按返回键来导航。


2、DialogFragment相比 Dialog的优势


DialogFragment 相比于传统的 Dialog 有以下几个优势:

  • 生命周期可控

    DialogFragment拥有自己的生命周期,能够更好地与ActivityFragment的生命周期进行协同。当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
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("标题")
            .setMessage("这是一个 DialogFragment")
            .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // 处理确定按钮点击事件
                }
            })
            .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // 处理取消按钮点击事件
                }
            });
        return builder.create();
    }
}

要显示该 DialogFragment,只需要在 Activity 中执行以下代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 显示 DialogFragment
        showDialogFragment();
    }

    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 {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化操作
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // 加载布局
        return inflater.inflate(R.layout.fragment_my, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        // 初始化视图组件
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // 清理操作,如取消动画、移除监听器等
    }

    @Override
    public 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>() {
    @Override
    protected Void doInBackground(Void... voids) {
        // 长时间运行的操作
        return null;
    }

    @Override
    protected 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、使用 FragmentnewInstance 方法

这是一种创建 Fragment 实例的推荐方式,它使得传递参数变得更加容易。

复制
public static MyFragment newInstance() {
    MyFragment fragment = new MyFragment();
    Bundle args = new Bundle();
    // 向 args 中添加参数
    fragment.setArguments(args);
    return fragment;
}

10、避免内存泄漏

确保在 onDestroyonDestroyView 中清理资源,如移除监听器、取消动画等。

@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 应用。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

邮件群发还能用吗

邮件群发仍然可以使用。不过&#xff0c;在进行邮件群发时&#xff0c;可能会遇到一些问题&#xff0c;如选择合适的邮件群发软件、应对垃圾邮件过滤器的挑战、管理收件人列表、邮件内容的个性化和定制、邮件投递的时间管理以及避免被列入黑名单等。 为了优化邮件群发的效果&a…

微信小程序知识点归纳(一)

前言&#xff1a;适用于有一定基础的前端开发同学&#xff0c;完成从网页开发到小程序开发的知识转换。 先立框架&#xff0c;后砌墙壁 回顾&#xff1a;了解微信小程序开发流程-CSDN博客 初始页面结构&#xff0c;三部分pages、utils、配置&#xff0c;分别存放页面、工具类…

图形渲染在AI去衣技术中的奇妙之旅

在这个数字化飞速发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为了我们生活中不可或缺的一部分。它像一位神秘的魔法师&#xff0c;以其不可思议的力量改变着我们的世界。今天&#xff0c;我要和大家探讨的&#xff0c;是一个颇具争议却技术含金量极高的话…

PostgreSQL自带的命令行工具13- pg_waldump

PostgreSQL自带的命令行工具13- pg_waldump 基础信息 OS版本&#xff1a;Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a;16.2 pg软件目录&#xff1a;/home/pg16/soft pg数据目录&#xff1a;/home/pg16/data 端口&#xff1a;5777pg_waldump 是 Po…

【C++历练之路】红黑树——map与set的封装实现

W...Y的个人主页&#x1f495; gitee代码仓库分享&#x1f60a; 前言&#xff1a;上篇博客中&#xff0c;我们为了使二叉搜索树不会出现”一边倒“的情况&#xff0c;使用了AVL树对搜索树进行了处理&#xff0c;从而解决了数据在有序或者接近有序时出现的情况。但是AVL树还会…

【编码利器 —— BaiduComate】

目录 1. 智能编码助手介绍 2. 场景需求 3. 功能体验 3.1指令功能 3.2插件用法 3.3知识用法 3.4自定义配置 4. 试用感受 5. AI编程应用 6.总结 智能编码助手是当下人工智能技术在编程领域的一项重要应用。Baidu Comate智能编码助手作为一款具有强大功能和智能特性的工…

EPAI手绘建模APP数值几何变换

(10) 数值几何变换 图 257 数值几何变换工具栏 ① 数值几何变换和交互式几何变换都包括移动、旋转、缩放模型。但是交互式几何变换变换时的变换轴是模型自身中心为变换中心&#xff0c;以X、Y、Z方向的为变换方向&#xff0c;而数值几何变换可以指定变换中心和变换方向。另外&a…

HarmonyOS NEXT应用开发之多模态页面转场动效实现案例

介绍 本示例介绍多模态页面转场动效实现&#xff1a;通过半模态转场实现半模态登录界面&#xff0c; 与全屏模态和组件转场结合实现多模态组合登录场景&#xff0c;其中手机验证码登录与账号密码登录都为组件&#xff0c; 通过TransitionEffect.move()实现组件间转场达到近似页…

使用Portal V17搜索PN(profinet)设备的方法

这里的PN就是profinet&#xff0c;无需连接PLC&#xff0c;只需要将PN设备连接电脑即可&#xff0c;如下图&#xff0c; 跳出如下窗口&#xff0c; 点击start search 搜索完毕后就看到PN设备的名字啦&#xff1a; 是不是很简单呢。

LeetCode--所有质数、质数对

1.0 Q: 输出 100 以内所有质数 1.1 /* 第一层循环控制检查到哪个数* 第二层通过遍历除以每个比他小的数的方式,检查每个数是不是质数* 由于要遍历检查,设置一个标记,只要任意一次循环可以整除,我们就设置该标记为不是质数 */boolean isPrime true;for (int i 2; i < 100…

终于找到微信聊天记录SQLite数据库文件解密方法了,一起来看看吧!

https://github.com/xuchengsheng/ 获取当前登录微信的微信昵称、账号、手机号、邮箱、秘钥、微信Id、文件夹路径 将微信PC的多个聊天记录数据库合并为单一数据库文件 支持微信聊天对话窗口&#xff08;文本消息&#xff0c;引用消息&#xff0c;图片消息&#xff0c;表情消息…

STM32(六):定时器PWM呼吸灯 (标准库函数)

前言 上一篇文章已经介绍了如何用STM32单片机中的TIMER定时器来控制LED灯的交替闪烁&#xff0c;实现了点灯的第五种方式。这篇文章我们来介绍一下如何用STM32单片机中的定时器的PWM波来实现LED的“呼吸”。 一、实验原理 关于定时器这边就不多加赘述&#xff0c;详细请看上…

【吊打面试官系列】Java高并发篇 - 如何让正在运行的线程暂停一段时间?

大家好&#xff0c;我是锋哥。今天分享关于 【如何让正在运行的线程暂停一段时间&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 如何让正在运行的线程暂停一段时间&#xff1f; 我们可以使用 Thread 类的 Sleep()方法让线程暂停一段时间。需要注意的是&#x…

ROS1集成NanoSDK(mqtt over quic)库遇到的问题

集成方式&#xff0c;demo见附件 问题记录 ROS集成构建问题&#xff1a;如下图&#xff0c;少了依赖库导致未定义的符号

AMD优化策略

FPGA&#xff0c;英文全称是 Field Programmable Gate Array&#xff0c;中文意思是现场可编程门阵列。基本架构&#xff1a;可配置逻辑模块&#xff08;CLB&#xff1a; Configurable Logic Block&#xff09;、开关矩阵&#xff08;Switch Matrix&#xff0c;也称为 Switch B…

kraken2 最新版安装,极简模式

kraken2 git clone https://github.com/DerrickWood/kraken2.gitcd kraken2./install_kraken2.sh /opt/krakenvim .bashrc ---------------- # Kraken export PATH"/opt/kraken:$PATH" ----------------source .bashrc Note: 不晓得是不是我设置了清华源&#xff0c…

【Django学习笔记(十)】Django的创建与运行

Django的创建与运行 前言正文1、安装Django2、创建项目2.1 基于终端创建项目2.2 基于Pycharm创建项目2.3 两种方式对比 3、默认项目文件介绍4、APP5、启动运行Django5.1 激活App5.2 编写URL和视图函数对应关系5.3 启动Django项目5.3.1 命令行启动5.3.2 Pycharm启动5.3.3 views.…

Web3智能物联网:科技连接的未来世界

在当今科技飞速发展的时代&#xff0c;Web3智能物联网正逐渐成为人们关注的焦点。随着区块链技术的不断成熟和普及&#xff0c;以及物联网的普及和应用&#xff0c;Web3智能物联网作为二者的结合&#xff0c;将为未来的数字世界带来革命性的变化。本文将深入探讨Web3智能物联网…

【JavaEE 初阶(三)】多线程代码案例

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多线程知识 目录 1.前言2.单例模式2.1饿汉方式2.2饿汉方式 3.阻塞队列3.1概念3.2实现 4.定时器4.1概念4.…

Linux常用名命令

Linux是一款免费的操作系统&#xff0c;用户可以通过网络或其他途径免费获得&#xff0c;并可以任意修改源代码&#xff0c;这是其他操作系统做不到的&#xff0c;Ubuntu&#xff0c;Centos。 linux中&#xff0c;一切皆文件。 一些重要的目录 / 根目录&#xff0c;所有文件都放…
最新文章