“不保留活动”打开,导致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个方法!
案例:电脑出现系统错误该如何解决? 【这几天长时间使用我的电脑,导致它的系统出现了错误。有没有小伙伴知道如何解决电脑系统出错的问题?求一个能快速解决的方法。】 电脑系统出现错误是使用电脑时难免会遇到的问题之一…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
