“不保留活动”打开,导致app返回前台崩溃问题解决
问题描述
不保留活动开关打开,把app切入后台,会导致当前展示的Activity被回收,切到前台后重建。
我们有个业务场景是,Activity里面有个ViewPager2,VP里面放Fragment,Fragment的展示需要在Activity中做一些逻辑判断,然后才把ViewPager2的adapter set给ViewPager2,进而Fragment才展示出来(在showContent函数中做的)。在正常情况下,是没有问题的,看log1,A表示Activity,F表示Fragment。
2023-04-24 11:48:14.880 27631-27631/com.sohu.sohuvideo E/lzy: A onCreate
2023-04-24 11:48:14.929 27631-27631/com.sohu.sohuvideo E/lzy: A onStart
2023-04-24 11:48:14.934 27631-27631/com.sohu.sohuvideo E/lzy: A onResume
2023-04-24 11:48:14.970 27631-27631/com.sohu.sohuvideo E/lzy: A showContent
2023-04-24 11:48:14.981 27631-27631/com.sohu.sohuvideo E/lzy: A showContent
2023-04-24 11:48:14.996 27631-27631/com.sohu.sohuvideo E/lzy: F onCreate
2023-04-24 11:48:14.996 27631-27631/com.sohu.sohuvideo E/lzy: F onCreateView
2023-04-24 11:48:14.999 27631-27631/com.sohu.sohuvideo E/lzy: F onViewCreated
2023-04-24 11:48:15.003 27631-27631/com.sohu.sohuvideo E/lzy: F onStart
2023-04-24 11:48:15.004 27631-27631/com.sohu.sohuvideo E/lzy: F onResume()
我们把“不保留活动”开关打开,点击home键切入后台,执行流程如下。
可以看到Activity和Fragment都被回收了
2023-04-24 11:49:37.176 27631-27631/com.sohu.sohuvideo E/lzy: F onStop
2023-04-24 11:49:37.176 27631-27631/com.sohu.sohuvideo E/lzy: A onSaveInstanceState
2023-04-24 11:49:37.181 27631-27631/com.sohu.sohuvideo E/lzy: F onSaveInstanceState
2023-04-24 11:49:37.203 27631-27631/com.sohu.sohuvideo E/lzy: A onDestroy
2023-04-24 11:49:37.210 27631-27631/com.sohu.sohuvideo E/lzy: F onDestroy()
我们再把app切出到前台,Activity和Fragment都会重建,结果app崩溃了
2023-04-23 14:11:35.851 11874-11874/? E/AndroidRuntime: FATAL EXCEPTION: mainProcess: com.sohu.sohuvideo, PID: 11874kotlin.UninitializedPropertyAccessException: lateinit property firstPageSessionListForeverLiveData has not been initializedat com.sohu.sohuvideo.chat.fragment.SessionListFragment.subscribeToModel(SessionListFragment.kt:3)at com.sohu.sohuvideo.chat.fragment.SessionListFragment.onViewCreated(SessionListFragment.kt:8)at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:21)at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:25)at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:69)at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:4)at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:75)at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3)at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3)at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:1)at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:5)at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1433)at android.app.Activity.performStart(Activity.java:7976)at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3544)at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:226)at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:206)at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:178)at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:102)at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2245)at android.os.Handler.dispatchMessage(Handler.java:107)at android.os.Looper.loop(Looper.java:237)at android.app.ActivityThread.main(ActivityThread.java:7840)at java.lang.reflect.Method.invoke(Native Method)at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:985)
崩溃的原因是,Fragment里有个lateinit属性没有被赋值,看代码逻辑是这个属性是在Activity中创建Fragment的时候传进来的,Fragment是在ViewPager2的Adapter中创建的。说明切到前台,执行流程是正常打开是不一样的,所以才导致这个问题。
切到前台执行流程如下
2023-04-24 11:50:28.542 27631-27631/com.sohu.sohuvideo E/lzy: A onCreate
2023-04-24 11:50:28.547 27631-27631/com.sohu.sohuvideo E/lzy: F onCreate
2023-04-24 11:50:28.576 27631-27631/com.sohu.sohuvideo E/lzy: A onStart
2023-04-24 11:50:28.609 27631-27631/com.sohu.sohuvideo E/lzy: F onCreateView
2023-04-24 11:50:28.610 27631-27631/com.sohu.sohuvideo E/lzy: F onViewCreated
2023-04-24 11:50:28.612 27631-27631/com.sohu.sohuvideo E/lzy: F onStart
2023-04-24 11:50:28.614 27631-27631/com.sohu.sohuvideo E/lzy: A onRestoreInstanceState
2023-04-24 11:50:28.616 27631-27631/com.sohu.sohuvideo E/lzy: A onResume
2023-04-24 11:50:28.621 27631-27631/com.sohu.sohuvideo E/lzy: F onResume()
2023-04-24 11:50:28.656 27631-27631/com.sohu.sohuvideo E/lzy: A showContent
2023-04-24 11:50:30.143 27631-27631/com.sohu.sohuvideo E/lzy: A showContent
我们发现切到前台,Fragment和Activity会重建,生命周期的执行流程如上,这个是因为系统知道这些被回收了,自动重建的。而Fragment中使用firstPageSessionListForeverLiveData是在onViewCreated,所以就报错了。
问题的解决
其实这个问题拔高一点,是activity和Fragment、Fragment和Fragment之前共享数据的问题,我们可以把需要共享的数据,放到依附Activity的ViewModel中,这样只要能获取到这个ViewModel实例就能拿到共享数据,而不是放在Activity中让Activity传给Fragment。
以上面的问题为例,firstPageSessionListForeverLiveData放在ViewModel里面,Fragment被重建的时候,可以直接从Activity的ViewModel中直接拿到这firstPageSessionListForeverLiveData。就可以解决这个问题。
这里需要说明的是,Activity重建后,按照执行流程还是会执行到给ViewPager2设置Adapter的流程中,但是,实际上已经不会再去场景Fragment了,也就是不会再执行Adapter的createFragment函数了。这个不知道为什么,应该是这种销毁重建有特殊处理吧,能把重建的Fragment和ViewPager2能自动关联起来,这块可以以后研究。其实也就是应该这个原因才有的崩溃。
locateTab()是去定位展示哪个Fragment的,是可以正常执行的
private void showContent(boolean isDataNotEmpty) {Log.e("lzy", "A showContent");PullListMaskController.ListViewState newState = isDataNotEmpty ? PullListMaskController.ListViewState.LIST_REFRESH_COMPLETE : PullListMaskController.ListViewState.EMPTY_BLANK;LogUtils.d(TAG, "fyf--------showContent(): mCurrentState = " + mCurrentState + ", newState = " + newState);if (mCurrentState != newState) {mCurrentState = newState;if (mCurrentState == PullListMaskController.ListViewState.LIST_REFRESH_COMPLETE) {viewBinding.fragmentViewPager.setAdapter(new SessionPagerAdapter(this));viewBinding.slidingTabLayout2.setViewPager(viewBinding.fragmentViewPager, new String[]{"我关注的", "粉丝来信"});viewPagerReady = true;locateTab();showViewStatusWhenResponse(PullListMaskController.ListViewState.LIST_REFRESH_COMPLETE);onFollowUnReadChange();onOtherUnReadChange();} else {showViewStatusWhenResponse(PullListMaskController.ListViewState.EMPTY_BLANK);}}}private class SessionPagerAdapter extends FragmentStateAdapter {public SessionPagerAdapter(@NonNull FragmentActivity fragmentActivity) {super(fragmentActivity);}@NonNull@Overridepublic Fragment createFragment(int position) {SessionListFragment mFragment = new SessionListFragment();Bundle bundle = new Bundle();LogUtils.d(TAG, "fyf--------createFragment(): ");if (position == 0) {bundle.putString(SessionListFragment.TAB_TYPE, SessionListFragment.MY_ATTENTION);followFragment = mFragment;
// followFragment.setSessionLiveData(followTabLiveData);
// followFragment.setFirstPageSessionLiveData(followTabFirstPageLiveData);} else {bundle.putString(SessionListFragment.TAB_TYPE, SessionListFragment.OTHER);otherFragment = mFragment;
// otherFragment.setSessionLiveData(otherTabLiveData);
// otherFragment.setFirstPageSessionLiveData(otherTabFirstPageLiveData);}mFragment.setArguments(bundle);mFragment.setCallBack(new SessionListFragment.ICallback() {@Overridepublic int getTotalItemCount() {int totalCount = 0;if (followFragment != null) {totalCount += followFragment.getItemCount();}if (otherFragment != null) {totalCount += otherFragment.getItemCount();}return totalCount;}});return mFragment;}
还有一点需要说明的是,ViewPager2是有两个tab,也就是有两个Fragment,如果两个Fragment都创建过,销毁重建的时候,两个Fragment都会重建出来,确定了展示那个Fragment了之后,另一个Fragment又被销毁了,不知道为什么。
2023-04-24 14:54:39.100 7400-7400/? E/lzy: A onCreate
2023-04-24 14:54:39.106 7400-7400/? E/lzy: F onCreate
2023-04-24 14:54:39.106 7400-7400/? E/lzy: F onCreate
2023-04-24 14:54:39.138 7400-7400/? E/lzy: A onStart
2023-04-24 14:54:39.186 7400-7400/? E/lzy: F onCreateView
2023-04-24 14:54:39.187 7400-7400/? E/lzy: F onViewCreated
2023-04-24 14:54:39.190 7400-7400/? E/lzy: F onCreateView
2023-04-24 14:54:39.191 7400-7400/? E/lzy: F onViewCreated
2023-04-24 14:54:39.193 7400-7400/? E/lzy: F onStart
2023-04-24 14:54:39.193 7400-7400/? E/lzy: F onStart
2023-04-24 14:54:39.198 7400-7400/? E/lzy: A onRestoreInstanceState
2023-04-24 14:54:39.199 7400-7400/? E/lzy: A onResume
2023-04-24 14:54:39.203 7400-7400/? E/lzy: F onResume()
2023-04-24 14:54:39.232 7400-7400/? E/lzy: A showContent
2023-04-24 14:54:39.236 7400-7400/? E/lzy: F onPause
2023-04-24 14:54:39.236 7400-7400/? E/lzy: F onResume()
2023-04-24 14:54:39.330 7400-7400/? E/lzy: A showContent
2023-04-24 14:54:49.237 7400-7400/? E/lzy: F onSaveInstanceState
2023-04-24 14:54:49.243 7400-7400/? E/lzy: F onStop
2023-04-24 14:54:49.247 7400-7400/? E/lzy: F onDestroy()
看上面的log,最后两行log,切出前台后,两个Fragment都被重建了,最后有一个被销毁了
参考
Android开发之InstanceState详解
Fragment 的过去、现在和将来
相关文章:
“不保留活动”打开,导致app返回前台崩溃问题解决
问题描述 不保留活动开关打开,把app切入后台,会导致当前展示的Activity被回收,切到前台后重建。 我们有个业务场景是,Activity里面有个ViewPager2,VP里面放Fragment,Fragment的展示需要在Activity中做一些…...
解读vue3源码(3)——watch
Vue3的watch底层源码主要是通过使用Proxy对象来实现的。在Vue3中,每个组件实例都会有一个watcher实例,用于监听组件数据的变化。当组件数据发生变化时,watcher实例会触发回调函数,从而更新组件的视图。 Vue3的watch底层源码主要涉…...
优秀简历的HR视角:怎样打造一份称心如意的简历?
简历的排版应该简洁工整,注重细节。需要注意对齐和标点符号的使用,因为在排版上的细节需要下很大功夫。除此之外,下面重点讲述几点简历内容需要注意的地方。 要点1:不相关的不要写。 尤其是与应聘岗位毫不相关的实习经历&#x…...
系统集成项目管理工程师——考试重点(三)项目管理一般知识
1.项目定义: 为达到特定的目的,使用一定资源,在确定的期间内,为特定发起人提供独特的产品、服务或成果而进行的一系列相互关联的活动的集合。 2.项目目标: 成果性目标:项目产品本身 约束性目标&…...
为什么医疗保健需要MFT来帮助保护EHR文件传输
毫无疑问,医疗保健行业需要EHR技术来处理患者,设施,提供者等之间的敏感患者信息。但是,如果没有安全的MFT解决方案,您将无法安全地传输患者文件,从而使您的运营面临遭受数据泄露,尴尬࿰…...
对项目总体把控不足,项目经理应该怎么办?
公司现状:项目人员紧缺,只有两人了解此项目技术细节,其中一个不常驻现场,另一个是执行项目经理李伟。 项目经理王博是公司元老,同时负责多个项目,工作比较忙,不常驻现场,没有参加过…...
【学习笔记】CF603E Pastoral Oddities
先不考虑数据结构部分,尝试猜一下结论。 结论:一个连通块有解当且仅当连通块的度数为偶数。 然后这题要你最大边权最小。最无脑的方法就是直接上 lct \text{lct} lct。真省事啊 我第一眼想到的还是整体二分。这玩意非常好写。 但是为什么也可以用线段…...
如何使用ESP32-CAM构建一个人脸识别系统
有许多人识别系统使用签名、指纹、语音、手部几何、人脸识别等来识别人,但除了人脸识别系统。 人脸识别系统不仅可以用于安全目的来识别公共场所的人员,还可以用于办公室和学校的考勤目的。 在这个项目中,我们将使用 ESP32-CAM 构建一个人脸识…...
JavaWeb分页条件查询参数特殊字符处理
问题背景 在项目开发过程中,基本都会有列表条件查询,例如用户管理会有通过用户姓名模糊查询用户,课程管理会有课程名称模糊查询课程等等。 而查询过程中如果用户在界面上输入一些特殊字符,例如:%_等等,这…...
ubuntu18服务安装
一、JDK安装 将jdk解压缩到该目录 /opt/ sudo tar -zxvf jdk-8u261-linux-x64.tar.gz -C /opt/ #重命名 cd /opt sudo mv jdk-8u261-linux-x64 jdk_8 修改环境变量 sudo vi ~/.bashrc #在文件最后追加以下文本 #进入编辑器后输入以下指令: #1. G //将光标移到最后一…...
这些使用工具大推荐,现在知道不晚
1.Snip Snip是一款截图软件,它突出的优点就是可以制作滚动截图。 例如:对整个网页进行截图,使用Snip即可轻松获取,无需处理水印。 2.Sleep Cycle 快节奏、高压力的生活导致我们越来越晚睡觉,睡眠质量越来越差。 想提…...
【Java|golang】1048. 最长字符串链
给出一个单词数组 words ,其中每个单词都由小写英文字母组成。 如果我们可以 不改变其他字符的顺序 ,在 wordA 的任何地方添加 恰好一个 字母使其变成 wordB ,那么我们认为 wordA 是 wordB 的 前身 。 例如,“abc” 是 “abac”…...
Hive基础和使用详解
文章目录 一、启动hive1. hive启动的前置条件2. 启动方式一: hive命令3. 方式二:使用jdbc连接hive 二、Hive常用交互命令1. hive -help 命令2. hive -e 命令3. hive -f 命令4. 退出hive窗口5. 在hive窗口中执行dfs -ls /; 三、Hive语法1.DDL语句1.1 创建数据库1.2 两…...
c/c++:栈帧,传值,传址,实参传值给形参,传地址指针给形参
c/c:栈帧,传值,传址,实参传值给形参,传地址指针给形参 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,此时学会c的话, 我所知道的周边的会c的同学&…...
玩元宇宙血亏后 蓝色光标梭哈AI也挺悬
蓝色光标2022年年度报告出炉,巨亏21.75 亿元,其中20.38亿亏损因商誉、无形资产及其他资产减值造成,而在实际亏损业务中,元宇宙占比不小。 蓝色光标在元宇宙领域的布局,主要通过三家子公司实施,分别为蓝色宇…...
生物---英文
标题 前言必学场景词汇及用法鸟类昆虫类哺乳类爬行类情境常用单词鸟类虫类哺乳类两栖类与爬行类分类与动物相关的习语前言 加油 必学场景词汇及用法 鸟类 1bird [b[插图]d] n.鸟bird’s-eye-view[ˈb[插图]dzaɪˌvju]adj.鸟瞰图的a bird’s-eye view鸟瞰a flock of bird…...
ENVI 国产高分2号(GF-2)卫星数据辐射定标 大气校正 影像融合
1.数据 高分2号卫星数据,包含: MSS-1\2多光谱数据,4m分辨率; Pan-1\2全色波段数据,0.8m分辨率。 2.处理软件 ENVI5.3 国产插件下载地址:ENVI App Store (geoscene.cn) 首先下载插件文件; …...
操作系统考试复习——第二章 进程控制 同步与互斥
进程控制一般是由OS中的原语来实现的。 大多数OS内核都包含了两大方面的功能: 1.支撑功能:1)中断处理 2)时钟管理 3)原语操作(原语操作就是原子操作。所谓原子操作就是一个操作中所有动作要不全做要不全不做) 2.资源管理功能:1)进程管理…...
mac gitstats查看git提交记录
一、介绍: 进一步来讲,Gitstats它是一个git仓库分析软件,它可以检查仓库并生成历史数据的统计信息。可以帮助你查看git仓库的提交状态,根据不同维度分析计算,并自动生成数据图表。 官网介绍:http://gitst…...
电脑系统错误怎么办?您可以看看这5个方法!
案例:电脑出现系统错误该如何解决? 【这几天长时间使用我的电脑,导致它的系统出现了错误。有没有小伙伴知道如何解决电脑系统出错的问题?求一个能快速解决的方法。】 电脑系统出现错误是使用电脑时难免会遇到的问题之一…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
