【问题标题】:Do we need to handle weak reference and context switching?我们需要处理弱引用和上下文切换吗?
【发布时间】:2021-08-29 10:58:34
【问题描述】:

为了缓解内存泄漏,我们在不同线程上运行的内部类中保留了活动的弱引用。我们检查weakreference.get() 是否为非空,然后再继续。如果当我们检查weakreference.get() 为非空但发生垃圾回收时,我们是否需要一次又一次地检查引用是否为非空,或者我是否遗漏了什么?

public class MainActivity extends Activity {    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyAsyncTask(this).execute();
    }    
    private static class MyAsyncTask extends AsyncTask {
        private WeakReference<MainActivity> mainActivity;    
        
        public MyAsyncTask(MainActivity mainActivity) {   
            this.mainActivity = new WeakReference<>(mainActivity);            
        }       
        @Override
        protected Object doInBackground(Object[] params) {
            return doSomeStuff();
        }        
        @Override
        protected void onPostExecute(Object object) {
            super.onPostExecute(object);
            if (mainActivity.get() != null){
                //do something
                //context switching and garbage collection happen
                //again do a null check?
            }
        }
    }
}

【问题讨论】:

    标签: android garbage-collection weak-references context-switching


    【解决方案1】:

    你应该这样做:

    MainActivity temp = mainActivity.get();
    if (temp != null){
        // Use 'temp' to access the `MainActivity`
    }
    

    假设temp 不是null,您现在在实时变量中拥有MainActivity 对象的常规引用这一事实意味着该对象是强可访问的。垃圾收集器不会收集它。

    (事实上,只要temp 仍然可以访问,GC 就不会破坏您的WeakReference。规范规定,如果ref 是强可达的。)


    但另一方面,如果您没有对 MainActivity 的强引用,那么 GC 可能 随时破坏 WeakReference。因此,您应该始终检查get() 调用的结果。

    【讨论】:

    • 所以从这里开始,首先创建一个强引用,然后做一个空检查。另一个警告是避免在 if 块中进行耗时的操作以快速释放引用以避免从 GC 收集中停止它,我正确吗?
    • 还有一件事,如果活动处于非法状态,或者即使我们有很强的参考,也可能进入非法状态,如何避免这种情况?
    • 1) 是的。 2)可能没有。如果您出于某种目的需要MainActivity,那么最好长时间使用强引用,而不是必须经历重新实例化它的所有麻烦。 3) 强引用或弱引用与此无关。两者都无法避免活动进入非法状态。
    • 当我持有对它的引用时,它可以进入其他状态吗?
    • 持有一个引用不会停止一个活动改变状态。
    【解决方案2】:

    您应该检查对变量的每次访问的非空状态。 但是......还有一个额外的问题,你必须在使用它之前考虑活动状态(我的意思是生命周期状态)。

    【讨论】:

    • 感谢您提及状态,但即使在我检查之后它不是空的,即使在再次使用参考时(检查后)它也可能被收集对吗?或者问题可以在两个高级指令调用之间进行 GC?
    猜你喜欢
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 2014-10-23
    相关资源
    最近更新 更多