From 9c91839520828daa154edc9f5ea492fb4805a31f Mon Sep 17 00:00:00 2001 From: zhanglei <350328959@qq.com> Date: Fri, 6 Mar 2026 10:25:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(base):=20=E4=BF=AE=E5=A4=8D=E5=A4=9A?= =?UTF-8?q?=E5=A4=84=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F=E5=8F=8A=E7=94=9F?= =?UTF-8?q?=E5=91=BD=E5=91=A8=E6=9C=9F=E5=AE=89=E5=85=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BaseVMBFragment: - 修复 onDestroyView 中 mBinding == null(比较运算)为正确的 _mBinding = null(赋值), 引入 backing field 模式彻底释放 View 引用,防止 Fragment 回退栈内存泄漏 - 修复 onDestroy 中 EventBus.unregister 判断条件取反(!isRegistered → isRegistered), 确保 Fragment 销毁时正确注销,避免 EventBus 长期持有 Fragment 引用 BaseVMBActivity: - 删除无效的 getResources() 重写(createConfigurationContext 返回值未使用), 字体防缩放逻辑已由 attachBaseContext 正确实现 MainActivity: - 删除 onSaveInstanceState(Bundle()) 错误重写, 传入空 Bundle 导致 Fragment 状态无法保存,低内存恢复场景必现异常 EmergencyFragment: - onDestroy 中补充主动停止并销毁 AMapLocationClient, 防止 Fragment 销毁后 GPS 定位服务持续运行 HomeFragment: - homeNoticeStartRepeat 新增 Job 引用,每次启动前取消旧协程, 防止多次调用时多个轮询协程并发叠加导致接口重复请求 WatchItemFragment: - newInstance 迁移至 companion object,符合 Android Fragment 工厂方法规范 - position 类型由 Int? 改为 Int,移除无用的 Fragment import Co-Authored-By: Claude Sonnet 4.6 --- .../com/xjjk/healthyclients/MainActivity.kt | 3 --- .../healthyclients/base/BaseVMBActivity.kt | 9 ------- .../healthyclients/base/BaseVMBFragment.kt | 18 ++++++++++---- .../fragment/EmergencyFragment.kt | 4 ++++ .../healthyclients/fragment/HomeFragment.kt | 9 +++++-- .../fragment/WatchItemFragment.kt | 24 ++++++++++++------- .../xjjk/healthyclients/view/HomeWatchView.kt | 2 +- 7 files changed, 40 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/xjjk/healthyclients/MainActivity.kt b/app/src/main/java/com/xjjk/healthyclients/MainActivity.kt index efc5de2..21b051d 100644 --- a/app/src/main/java/com/xjjk/healthyclients/MainActivity.kt +++ b/app/src/main/java/com/xjjk/healthyclients/MainActivity.kt @@ -272,9 +272,6 @@ class MainActivity : BaseVMBActivity(R.layou super.onPause() } - override fun onSaveInstanceState(outState: Bundle) { - super.onSaveInstanceState(Bundle()) - } override fun getFragmentByTag(tabTag: String): Fragment? { when (tabTag) { diff --git a/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBActivity.kt b/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBActivity.kt index bf9ceec..66056cc 100644 --- a/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBActivity.kt +++ b/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBActivity.kt @@ -70,15 +70,6 @@ abstract class BaseVMBActivity(private var mEmpty: View?=null var mRootView:RelativeLayout?=null - /** - * 重写getResources()方法,让APP的字体不受系统设置字体大小影响 - */ - override fun getResources(): Resources? { - val config = Configuration() - config.setToDefaults() - createConfigurationContext(config) - return super.getResources() - } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBFragment.kt b/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBFragment.kt index 0526cb3..815a2db 100644 --- a/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBFragment.kt +++ b/app/src/main/java/com/xjjk/healthyclients/base/BaseVMBFragment.kt @@ -56,15 +56,21 @@ abstract class BaseVMBFragment(private private var mIsFirstLoading = true var dialog: LoadingDialog? = null protected lateinit var mViewModel: VM - lateinit var mBinding: B + + /** ViewDataBinding 可空 backing field,onDestroyView 时置 null 防止内存泄漏 */ + private var _mBinding: B? = null + + /** 对外暴露的非空 getter,仅在 onCreateView ~ onDestroyView 生命周期内有效 */ + val mBinding: B get() = _mBinding!! + var mEmpty: View? = null override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - mBinding = DataBindingUtil.inflate(inflater, contentViewResId, container, false) - return mBinding.root + _mBinding = DataBindingUtil.inflate(inflater, contentViewResId, container, false) + return _mBinding!!.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -306,13 +312,15 @@ abstract class BaseVMBFragment(private } override fun onDestroyView() { - mBinding == null super.onDestroyView() + // 置 null 释放 View 引用,防止 Fragment 回退栈期间内存泄漏 + _mBinding = null } override fun onDestroy() { super.onDestroy() - if (!EventBus.getDefault().isRegistered(this)) { + // 已注册才执行注销,避免 EventBus 持有 Fragment 引用 + if (EventBus.getDefault().isRegistered(this)) { EventBus.getDefault().unregister(this) } } diff --git a/app/src/main/java/com/xjjk/healthyclients/fragment/EmergencyFragment.kt b/app/src/main/java/com/xjjk/healthyclients/fragment/EmergencyFragment.kt index e9f841e..791b50b 100644 --- a/app/src/main/java/com/xjjk/healthyclients/fragment/EmergencyFragment.kt +++ b/app/src/main/java/com/xjjk/healthyclients/fragment/EmergencyFragment.kt @@ -180,6 +180,10 @@ class EmergencyFragment : override fun onDestroy() { super.onDestroy() + // 主动停止并销毁定位客户端,防止 Fragment 销毁后 GPS 定位服务持续运行造成资源浪费 + mlocationClient?.stopLocation() + mlocationClient?.onDestroy() + mlocationClient = null mMapView?.onDestroy() } diff --git a/app/src/main/java/com/xjjk/healthyclients/fragment/HomeFragment.kt b/app/src/main/java/com/xjjk/healthyclients/fragment/HomeFragment.kt index cb5a3c1..0f36a8c 100644 --- a/app/src/main/java/com/xjjk/healthyclients/fragment/HomeFragment.kt +++ b/app/src/main/java/com/xjjk/healthyclients/fragment/HomeFragment.kt @@ -32,6 +32,7 @@ import com.xjjk.healthyclients.ui.viewmodel.HomeViewModel import com.xjjk.healthyclients.utils.ConstantUtils import com.xjjk.healthyclients.utils.IMInputActionSettingUtils import com.xjjk.healthyclients.utils.TUIUtils +import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -49,9 +50,11 @@ class HomeFragment : var mGuidanceFragmentDoctorAdapter: GuidanceFragmentDoctorAdapter? = null var REQUEST_DURATION = 1000 * 120L - var noticeTime = REQUEST_DURATION + /** 通知轮播协程 Job,重新启动前先取消旧任务,防止多协程并发叠加 */ + private var noticeJob: Job? = null + override fun initView(root: View?, savedInstanceState: Bundle?) { mBinding.swipeRefresh.initColors() @@ -339,7 +342,9 @@ class HomeFragment : } private fun homeNoticeStartRepeat() { - lifecycleScope.launch { + // 取消旧的轮询协程,防止多次调用时多个协程并发叠加 + noticeJob?.cancel() + noticeJob = lifecycleScope.launch { repeat(500) { mViewModel.getHomeNoticeListRepeat() delay(noticeTime) diff --git a/app/src/main/java/com/xjjk/healthyclients/fragment/WatchItemFragment.kt b/app/src/main/java/com/xjjk/healthyclients/fragment/WatchItemFragment.kt index 352dcef..10b8dce 100644 --- a/app/src/main/java/com/xjjk/healthyclients/fragment/WatchItemFragment.kt +++ b/app/src/main/java/com/xjjk/healthyclients/fragment/WatchItemFragment.kt @@ -3,7 +3,6 @@ package com.xjjk.healthyclients.fragment import android.os.Bundle import android.text.TextUtils import android.view.View -import androidx.fragment.app.Fragment import com.sw.healthyclients.utils.DateUtil import com.xjjk.healthyclients.R import com.xjjk.healthyclients.base.BaseVMBFragment @@ -20,18 +19,25 @@ import com.xjjk.healthyclients.ui.viewmodel.HomeViewModel */ class WatchItemFragment : BaseVMBFragment(R.layout.fragment_item_watch) { - var position: Int? = -1 - fun newInstance(position: Int): Fragment { - val args = Bundle() - args.putInt("position", position) - val fragment = WatchItemFragment() - fragment.arguments = args - return fragment + companion object { + /** + * 创建 WatchItemFragment 实例,通过 arguments 传入 Tab 位置 + * @param position Tab 位置(0=心率 1=血氧 2=压力 3=体温 4=睡眠) + */ + fun newInstance(position: Int): WatchItemFragment { + val args = Bundle() + args.putInt("position", position) + return WatchItemFragment().apply { + arguments = args + } + } } + private var position: Int = -1 + override fun initView(root: View?, savedInstanceState: Bundle?) { - position = arguments?.getInt("position") + position = arguments?.getInt("position") ?: -1 mBinding.watchTypeImg.setImageResource(getWatchTypeImg(position)) if (position != 4) { diff --git a/app/src/main/java/com/xjjk/healthyclients/view/HomeWatchView.kt b/app/src/main/java/com/xjjk/healthyclients/view/HomeWatchView.kt index a5ae5cd..69dec47 100644 --- a/app/src/main/java/com/xjjk/healthyclients/view/HomeWatchView.kt +++ b/app/src/main/java/com/xjjk/healthyclients/view/HomeWatchView.kt @@ -121,7 +121,7 @@ class HomeWatchView(context: Context?, attrs: AttributeSet?) : } override fun createFragment(position: Int): Fragment { - return WatchItemFragment().newInstance(position) + return WatchItemFragment.newInstance(position) } }