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

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

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

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

    Service 也是 Context 呀 直接在 service 里调 this.getAssets()不就行了
    kop1989
        11
    kop1989  
       151 天前
    你使用的 context 不会被销毁。

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

    public class ContextWrapper extends Context

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