[Android MVVM 架构笔记] 基于 Kotlin 延迟委托实现全局统一 Loading

📅 2026/6/26 4:26:59
[Android MVVM 架构笔记] 基于 Kotlin 延迟委托实现全局统一 Loading
在日常项目开发中,像“收藏、删除、分享、修改”这类由用户点击按钮触发的异步网络操作,在架构上被称为操作性动作(Action Operations)。传统的做法要么是在每个页面的 XML 布局中重复堆砌进度条组件(造成 XML 极度冗余),要么是在基类(BaseActivity/BaseFragment)中强行塞入 Dialog 的控制逻辑(导致基类极度膨胀且难以维护)。更致命的是,若异步协程在后台结束并尝试关闭 Loading 时宿主已被用户切入后台,传统的生命周期管理极易引发StateLoss异常导致 App 闪退。为了优雅地解决这一系列痛点,本方案遵循“单一职责原则”、“组合优于继承”以及“编译期绝对安全”的原则,将 Loading 业务完全从基类中剥离,利用 Kotlin 属性延迟委托(by lazy)实现“按需插拔装载”,并通过系统原生组件级双重泛型约束,确保了极高的运行稳定性与代码优雅度。一、 完整物理文件清单与物理路径布局文件: app/src/main/res/layout/dialog_loading.xml 唯一样式 XML:毛玻璃质感加载卡片 包名/ui/widget/loading: app/src/main/java/xxx/ui/widget/loading/ ├── LoadingDelegate.kt 核心契约:Kotlin 风格加载委托接口 ├── LoadingDialogFragment.kt 弹窗组件:生命周期安全 DialogFragment └── LoadingDelegateImpl.kt 契约实现:完全闭环的 Dialog 调度者 包名/util/ext: app/src/main/java/xxx/util/ext/ └── ActivityExt.kt 系统级扩展:原生组件编译期安全响应式绑定(注:请将路径中的xxx替换为您项目的实际根包名。)二、 完整源码实现1. 唯一样式 XML:dialog_loading.xml设计规范:采用 Material3 风格的 80% 半透明卡片,将整体 Loading 容器与具体页面布局 100% 解耦。?xml version="1.0" encoding="utf-8"?com.google.android.material.card.MaterialCardViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="center"app:cardCornerRadius="12dp"app:cardElevation="6dp"app:cardBackgroundColor="#CCFFFFFF"!-- 80% 不透明度白色 --com.google.android.material.progressindicator.CircularProgressIndicatorandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:indeterminate="true"app:indicatorSize="40dp"app:trackThickness="4dp"app:indicatorColor="#2F74E5"//com.google.android.material.card.MaterialCardView2. 核心控制契约:LoadingDelegate.ktpackagexxx.ui.widget.loading/** * 💡 纯净加载控制契约,在命名上与 Kotlin 的 by 委托机制对应 */interfaceLoadingDelegate{funshowLoading(show:Boolean)}3. 生命周期安全弹窗:LoadingDialogFragment.ktpackagexxx.ui.widget.loadingimportandroid.graphics.Colorimportandroid.graphics.drawable.ColorDrawableimportandroid.os.Bundleimportandroid.view.LayoutInflaterimportandroid.view.Viewimportandroid.view.ViewGroupimportandroidx.fragment.app.DialogFragmentimportxxx.R//