V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Vegetable
V2EX  ›  Android

问一个安卓开发相关的问题

  •  
  •   Vegetable · 2019-11-12 10:12:04 +08:00 · 11222 次点击
    这是一个创建于 1838 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我不是安卓开发,但是有些好奇这个机制↓:

    在抖音里边,我从某一个账号开始,查看他的粉丝,选中一个粉丝继续查看这个选中粉丝的粉丝.

    这样我可以一直打开新的页面,点击返回的话,会回到上一个页面,那这些历史记录是怎么处理的呢?

    如此往复下去可以打开足够多的个人详情页面导致 app 崩溃吗? 还是说那些页面会被回收掉,只保存了一个路径而已?

    29 条回复    2019-11-13 14:24:49 +08:00
    Vegetable
        1
    Vegetable  
    OP
       2019-11-12 10:18:49 +08:00
    嗯..验证了一下好像是会,几十个之后好像是会黑屏,复现不是很稳定.
    llcfays
        2
    llcfays  
       2019-11-12 10:20:02 +08:00
    Android 是栈视图,另外也可以设置[启动模式]( https://blog.csdn.net/mynameishuangshuai/article/details/51491074)的。
    751762476
        3
    751762476  
       2019-11-12 10:20:05 +08:00
    Edward4074
        4
    Edward4074  
       2019-11-12 10:20:59 +08:00
    页面会被回收,但页面中 View 的状态会被保留,页面对应的数据需要开发人员在对应的回调里处理才能保留
    Mrxxy
        5
    Mrxxy  
       2019-11-12 10:21:32 +08:00
    Android 中每个 Activity 即界面,会被放在一个栈中
    https://developer.android.com/guide/components/tasks-and-back-stack.html?hl=zh-CN
    tongyang
        6
    tongyang  
       2019-11-12 10:31:37 +08:00
    一般安卓的 app 不会做处理的,你这属于极端现象
    Vegetable
        7
    Vegetable  
    OP
       2019-11-12 10:34:39 +08:00
    @llcfays
    @751762476
    @Edward4074
    @Mrxxy
    感谢各位,看明白啦
    fhvch
        8
    fhvch  
       2019-11-12 10:38:13 +08:00   ❤️ 1
    一般来说 Android 中你看到每一个页面都是一个 activity 组件(也有可能是 fragment/view )
    如果是 activity 的话,Android 中 activity 是通过 栈(先进后出) 这种数据结构去存储的
    一般情况下,也就你看到的那种情况就是每次你点击一次粉丝 都会去生成一个新的 activity 然后存到 栈顶,也就是我们能够看到的~( 2 楼有说还有其它的启动 activity 的模式)
    如果真的是我说的这样子的话,每次都去启动一个新的 activity 不去做一些处理的话确实是会有问题的,启动几十个甚至上百的时候,很有可能会内存溢出导致 crash...
    raiz
        9
    raiz  
       2019-11-12 11:18:17 +08:00   ❤️ 1
    社交软件都会遇到这个问题, 表现由交互和稳定性妥协,开发者通过设置 Activity 的启动模式,可以决定上一个 activity 留不留在返回栈里,如果留,那么会出现你说的问题(测试会报内存泄漏),不留的话,用户可能会丢失路径。
    wvitas
        10
    wvitas  
       2019-11-12 11:29:05 +08:00
    启动模式了解下
    Goolge
        11
    Goolge  
       2019-11-12 16:17:23 +08:00
    监听 activity 生命周期 超过 N 个 finish 之前的 为了防止占用大量内存。具体你怎么处理看情况。
    charlieputon
        12
    charlieputon  
       2019-11-12 16:49:24 +08:00 via Android
    这种情况应该使用 single top 启动模式来启动 activity
    ukyoo
        13
    ukyoo  
       2019-11-12 17:18:21 +08:00
    这和启动模式有啥关系啊...很常见的情况就是商品详情页通过相似商品无限开下去, 最后肯定会 OOM 的
    BigDogWang
        14
    BigDogWang  
       2019-11-12 17:22:12 +08:00
    @fhvch 没有内存泄漏的话是不会崩溃的。后台活动在内存不足的情况下是会回收掉的
    BigDogWang
        15
    BigDogWang  
       2019-11-12 17:24:03 +08:00
    为啥这帖子里这么多人在误导。如果你没有内存泄漏的话,后台 Activity 过多是不会导致 OOM 的
    DeweyReed
        16
    DeweyReed  
       2019-11-12 18:05:39 +08:00
    请问有什么办法可以最效率地保存这个历史路径吗?
    jjhappyforever
        17
    jjhappyforever  
       2019-11-12 18:43:54 +08:00
    首先打开足够多的页面是会被回收的,页面回收机制是由系统控制的,APP 本身只不过是一直 new Activity,单个 Activity 占有内存很少的,所以不停的 new 也无所谓,但假如你真的开启页面过度,导致栈底端一些页面被回收了,也只是将回收数据持久化到本地,待你返回在通过 Bundle 恢复数据而已.所以开启页面过多导致 crash 概率几乎为 0.系统分配给 APP 内存有临界值,内存溢出是内存使用不当造成的,如图片,大文件等,但开启页面的 Activity 机制,安卓系统是绝对不会让之内存不足而 crash 的.
    janus77
        18
    janus77  
       2019-11-12 19:18:56 +08:00 via iPhone
    会爆栈
    如果需要处理的话,就跟代码的单例一样,永远只有一个页面。
    fhvch
        19
    fhvch  
       2019-11-12 19:51:06 +08:00
    @BigDogWang activity 对象是绝对的强引用!这种级别的引用就算是 app 再怎么内存不足也不会去回收的!
    ukyoo
        20
    ukyoo  
       2019-11-12 19:56:53 +08:00
    vigidroid
        21
    vigidroid  
       2019-11-12 20:13:10 +08:00 via iPhone
    @BigDogWang 没记错的话,android 中的内存回收是以进程为单位的。一般情况下,activity 栈中的所有 activity 都处于同一进程中,所以会内存会一直累积直到 oom
    ukyoo
        22
    ukyoo  
       2019-11-12 20:20:41 +08:00   ❤️ 1
    自己新建个 Activity, 在 onCreate 里分配个大内存的数组, 无限重复开页面.

    class DetailActivity1111 : AppCompatActivity(){


    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.acti111)

    val ints = IntArray(120000000)

    findViewById<Button>(R.id.btn).setOnClickListener {
    startActivity(Intent(this, DetailActivity1111::class.java))
    }
    }
    }


    最后崩溃的日志如下:
    JNI DETECTED ERROR IN APPLICATION: JNI IsInstanceOf called with pending exception java.lang.OutOfMemoryError: Failed to allocate a 480000016 byte allocation with 25165824 free bytes and 457MB until OOM, max allowed footprint 82083784, growth limit 536870912

    代码就两三行,不存在内存泄露. 所以回收栈底 Activity 来回收内存的说法不成立.


    再看官方文档: https://developer.android.com/guide/components/activities/activity-lifecycle#asem
    写的很明白: 系统永远不会直接终止 Activity 以释放内存,而是会终止 Activity 所在的进程。
    yukiww233
        23
    yukiww233  
       2019-11-12 20:25:19 +08:00
    @ukyoo #22 感谢。差点信了楼上说的,虽然自己做的应用都预防了循环路由
    BigDogWang
        24
    BigDogWang  
       2019-11-13 09:40:31 +08:00
    @vigidroid 你到底是不是安卓开发😂
    BigDogWang
        25
    BigDogWang  
       2019-11-13 09:44:44 +08:00
    @fhvch Activity 的 onSaveInstanceState 就是为了这种场景设计的。不过楼上有人做实验,崩了
    BigDogWang
        26
    BigDogWang  
       2019-11-13 09:49:47 +08:00
    A background activity (an activity that is not visible to the user and has been stopped) is no longer critical, so the system may safely kill its process to reclaim memory for other foreground or visible processes. If its process needs to be killed, when the user navigates back to the activity (making it visible on the screen again), its onCreate(Bundle) method will be called with the savedInstanceState it had previously supplied in onSaveInstanceState(Bundle) so that it can restart itself in the same state as the user last left it.

    https://developer.android.com/reference/android/app/Activity#ProcessLifecycle
    官方文档
    BigDogWang
        27
    BigDogWang  
       2019-11-13 09:52:27 +08:00
    @BigDogWang 淦,收回我的话,这个还真是杀进程的。看来对安卓的基础部分还存在误解
    qiibeta
        28
    qiibeta  
       2019-11-13 11:37:17 +08:00
    Activity 会直接内存一直增加直到 OOM,https://github.com/bytedance/scene 现在也是这样……想做 [超过多少个页面就把之前老页面销毁,等返回老页面的时候再恢复,来节省内存] 这样的功能,还没做
    imn1
        29
    imn1  
       2019-11-13 14:24:49 +08:00
    昨天帮老妈更新一下手机 app,打开 chrome,竟然看到 98 个 tab……98 个……呆了几秒
    比我桌面系统还狠
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2561 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 10:45 · PVG 18:45 · LAX 02:45 · JFK 05:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.