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

初学 Android,请教下关于 context 的问题

  •  
  •   Features · 2021-12-21 11:44:24 +08:00 · 10124 次点击
    这是一个创建于 1067 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我在 Service 使用 Context.getAssets()
    需要将 Activity.this 传入到 Service 中
    因为 Activity 在退出程序后,就会 destroyed()
    我担心传入 Service 的 Context 会跟随被销毁
    但经过我监测,实际运行中并没有被销毁
    这是什么原因呢?

    这种情况是可靠的吗? Context 总是不会被销毁吗?
    第 1 条附言  ·  2021-12-21 18:30:35 +08:00
    有些问题想再请教下大家:
    我做的是一个音乐播放器的 demo ,Service 在不断地更新播放器的 Seekbar ,也涉及到对 Seekbar 实例的调用
    按理说应用到后台以后,Seekbar 实例就被销毁了,这时候是不是也会导致内存泄漏?
    第 2 条附言  ·  2021-12-21 22:18:00 +08:00
    我看 Profiler 里,MyActivity 只是 stopped ,saved ,没有 destroyed
    这说明什么呢?
    我通过任务管理器杀死进程以后,Profiler 里的 MyActivity 才出现 destroyed
    26 条回复    2021-12-22 18:08:33 +08:00
    winterbells
        1
    winterbells  
       2021-12-21 12:09:33 +08:00 via Android
    这个方法实际用的是 application context 吧
    BigDogWang
        2
    BigDogWang  
       2021-12-21 12:12:48 +08:00
    这样会导致内存泄漏的,而且因为生命周期的问题 context 的一些方法会不能用
    qwertasdf
        3
    qwertasdf  
       2021-12-21 12:21:05 +08:00
    因为你在 Service 里面正在持有这个 Context ,所以不会被摧毁,这就是经典的内存泄露吧。
    Lin0936
        4
    Lin0936  
       2021-12-21 12:28:13 +08:00
    Service 跟垃圾回收站打过招呼了,这个 Context 我要用,你先别回收
    37927
        5
    37927  
       2021-12-21 12:30:34 +08:00
    Service 也是 Context 的子类,直接在 Service 里面使用 this.getAssets()就可以了,如果传入 Activity 的 Context ,关闭 Activity 后,Service 没有被销毁的话,会导致 Activity 不能被回收,造成内存泄露。
    crayygy
        6
    crayygy  
       2021-12-21 13:29:26 +08:00
    memory leak
    chengyiqun
        7
    chengyiqun  
       2021-12-21 14:09:17 +08:00
    @37927
    @qwertasdf
    如果直接使用全局静态的 Application 类获得 Context 可有问题?
    leo7723
        8
    leo7723  
       2021-12-21 14:32:04 +08:00
    @chengyiqun 内存泄漏是一个相对的概念,对象再应该被回收的时候没有回收才叫内存泄漏。applicationcontext 的生命周期只会长于 service 所以不会有泄漏问题。
    ProphetN
        9
    ProphetN  
       2021-12-21 14:36:32 +08:00
    补充一下,如果要持有 Activity 的实例的话,都建议使用弱引用。
    jinksw
        10
    jinksw  
       2021-12-21 14:55:03 +08:00
    你在 Service 使用 Context.getAssets()

    Service 也是 Context 呀 直接在 service 里调 this.getAssets()不就行了
    kop1989
        11
    kop1989  
       2021-12-21 15:03:03 +08:00
    你使用的 context 不会被销毁。

    这不是 Activity 生命周期的相关问题,而是 GC (垃圾回收)相关。当一个对象还存在引用时,虚机的垃圾回收机制就是不会回收这个对象。然后这就会导致此 Activity 在 Service 销毁前不会被销毁。也就是楼上说的内存泄露。
    loshine1992
        12
    loshine1992  
       2021-12-21 16:06:29 +08:00
    public abstract class Service extends ContextWrapper implements ComponentCallbacks2,
    ContentCaptureManager.ContentCaptureClient

    public class ContextWrapper extends Context

    ...
    ParfoisMeng
        13
    ParfoisMeng  
       2021-12-21 17:04:09 +08:00
    典型的内存泄漏。
    Features
        14
    Features  
    OP
       2021-12-21 18:27:46 +08:00
    @jinksw 嗯嗯,我原来并不知道 Service 也继承自 Context ,然后我就把 activity 实例传给 Service 的 Presenter 类
    现在改善了一下代码,把 Service 的实例传给 Presenter 类了。
    Features
        15
    Features  
    OP
       2021-12-21 18:35:47 +08:00
    @loshine1992 谢谢,刚刚知道 Service 也继承自 Context😂
    Features
        16
    Features  
    OP
       2021-12-21 18:37:44 +08:00
    @qwertasdf @Lin0936 @37927 @leo7723
    有些问题想再请教下大家:
    我做的是一个音乐播放器的 demo ,Service 在不断地更新播放器的 Seekbar ,也涉及到对 Seekbar 实例的调用
    按理说应用到后台以后,Seekbar 实例就被销毁了,这时候是不是也会导致内存泄漏?
    这个时候是不是应该放弃更新 Seekbar ?
    DCELL
        17
    DCELL  
       2021-12-21 19:47:22 +08:00
    Service 不应该持有 Seekbar ;或者 Service 不应该去做 UI 更新,你应该通过观察者或者通知 去驱动 Activity 更新 UI 。
    ------ 一个 7 年前做过 android 开发的屌丝留,虽然不知道现在 android 技术已经更新到什么地步了,可能我的回答也是错的。
    acidsweet
        18
    acidsweet  
       2021-12-21 20:34:31 +08:00
    主要曲解了:Activity 的生命周期 vs Java 对象的生命周期
    qwertasdf
        19
    qwertasdf  
       2021-12-21 21:38:37 +08:00
    @Features
    你如果持有了,就会导致内存泄露,除非你在 Service 里面主动释放,否则你每次切换的时候都会有一个新的 Seebar 实例在 service 。
    我年轻的时候应该是用广播来更改状态的,现在好像有 RxJava 之类的东西去更新状态
    john6lq
        20
    john6lq  
       2021-12-21 22:39:18 +08:00
    @Features 音乐播放器最简单了,正确的方式是 startService() 配合 bindService(),bind 成功拿到一个连接对象,通过它进行后续逻辑,多看看 GitHub 别人代码也就会了。
    https://developer.android.com/guide/components/bound-services?hl=zh-cn
    Lin0936
        21
    Lin0936  
       2021-12-22 09:35:52 +08:00   ❤️ 1
    @Features Service 去更新 UI 不是一个好的做法,现在推荐是通过 ViewModel 管理状态,然后 ViewModel 通知 Activity/Fragment 来更新
    zxjunz
        22
    zxjunz  
       2021-12-22 09:48:32 +08:00
    集美们,看到了吧,这就是典型的内存泄漏
    cenbiq
        23
    cenbiq  
       2021-12-22 10:42:18 +08:00
    @Features Service 持有 UI 对象本身就很离奇...楼上有给你推荐方法,说到底你需要的是某种通知机制,Service 在运行的时候能够“通知”UI 更新。
    lisongeee
        24
    lisongeee  
       2021-12-22 14:46:10 +08:00
    这里应该用广播或者 bind 做信息的传递吧
    Features
        25
    Features  
    OP
       2021-12-22 17:51:42 +08:00
    @lisongeee 是用的 Binder 传递,但是原理应该一样的吧?
    lisongeee
        26
    lisongeee  
       2021-12-22 18:08:33 +08:00
    @Features Binder 和 Broadcast 原理不一样
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2765 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 11:49 · PVG 19:49 · LAX 03:49 · JFK 06:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.