为何调用onDestroy后未创建新的Activity实例?
问题:为何Activity调用onDestroy后重启实例哈希值相同?
我编写了一个仅用于记录生命周期的简单Activity,代码如下:
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d("hello", "onCreate") Log.d("hello", this.toString()) } override fun onStart(){ super.onStart() Log.d("hello", "onStart") } override fun onResume(){ super.onResume() Log.d("hello", "onResume") } override fun onPause(){ super.onPause() Log.d("hello", "onPause") } override fun onStop(){ super.onStop() Log.d("hello", "onStop") } override fun onDestroy(){ super.onDestroy() Log.d("hello", "onDestroy") } }
我在API 30的设备上运行该应用,按下概览键并上滑应用以杀死进程,Logcat显示如下内容:
---------------------------- PROCESS STARTED (10930) for package com.example.viewmodel ---------------------------- 2023-12-13 14:32:06.935 10930-10930 hello com.example.viewmodel D onCreate 2023-12-13 14:32:06.935 10930-10930 hello com.example.viewmodel D com.example.viewmodel.MainActivity@2edf7d9 2023-12-13 14:32:07.010 10930-10930 hello com.example.viewmodel D onStart 2023-12-13 14:32:07.084 10930-10930 hello com.example.viewmodel D onResume 2023-12-13 14:32:10.573 10930-10930 hello com.example.viewmodel D onPause 2023-12-13 14:32:10.994 10930-10930 hello com.example.viewmodel D onStop 2023-12-13 14:32:11.634 10930-10930 hello com.example.viewmodel D onDestroy ---------------------------- PROCESS ENDED (10930) for package com.example.viewmodel ----------------------------
可以看到onDestroy方法已被调用,意味着Activity实例已被销毁。随后我从启动器重新启动应用,预期会看到Log.d("hello", this.toString())输出不同的值,但结果却完全相同:
---------------------------- PROCESS STARTED (10983) for package com.example.viewmodel ---------------------------- 2023-12-13 14:41:01.475 10983-10983 hello com.example.viewmodel D onCreate 2023-12-13 14:41:01.475 10983-10983 hello com.example.viewmodel D com.example.viewmodel.MainActivity@2edf7d9 2023-12-13 14:41:01.541 10983-10983 hello com.example.viewmodel D onStart 2023-12-13 14:41:01.604 10983-10983 hello com.example.viewmodel D onResume
请问为何调用onDestroy后未创建新的Activity实例?
解答
这并不是没有创建新的Activity实例,问题出在对象toString()输出的哈希值并非唯一标识实例的可靠依据:
- 默认情况下,Kotlin/Java中对象的toString()格式是
类名@十六进制哈希码,这个哈希码来自Object类的hashCode()方法。在Android的ART虚拟机中,当进程重启后,内存地址空间会被重新分配,但出于内存优化或地址复用的机制,新创建的对象完全有可能复用之前实例的内存地址,导致哈希码看起来和旧实例一致。 - 你看到的两次进程ID分别是10930和10983,这已经明确说明是两个完全独立的进程——不同进程的内存空间完全隔离,旧实例不可能跨进程存活,进程内的Activity必然是全新的实例。
如果要验证确实是新实例,可以添加一个实例级的随机变量来区分:
class MainActivity : AppCompatActivity() { private val instanceId = Random.nextInt() // 每个实例创建时生成唯一随机数 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d("hello", "onCreate, instanceId: $instanceId") Log.d("hello", this.toString()) } // 其余生命周期方法保持不变 }
重启应用后,你会看到每次的instanceId都不同,这就能证明确实创建了新的Activity实例。
内容的提问来源于stack exchange,提问作者VanechikSpace
相关产品推荐
相关产品推荐

