是否可以在onDestroy之后调用回调方法? [英] Is it possible for a callback method to be called after onDestroy?

查看:183
本文介绍了是否可以在onDestroy之后调用回调方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的应用程序的最新版本中,一些用户遇到了我无法重现的崩溃.当前只有运行LollipopSamsung设备有此问题,但这可能只是巧合. 在分析了堆栈跟踪和相关代码之后,我认为我可能已经找到了罪魁祸首.为了验证我的假设,我将代码简化为以下代码段:

In the latest version of my app, some users are experiencing a crash that I'm unable to reproduce. Currently only Samsung devices running Lollipop are having the issue, but that might just be coincidence. After analyzing the stack trace and relevant code, I think that I may have found the culprit. To test my assumption, I simplified the code to the snippet below:

public class TestActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Button b = new Button(this);
        b.setText("Click me!");
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new Handler().post(new Runnable() {
                    @Override
                    public void run() {
                        // This is the callback method
                        Log.d("TAG", "listenerNotified");
                    }
                });
            }
        });

        setContentView(b);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("TAG", "onDestroy");
    }

}

每次我通过先点击 Click me 按钮,然后在onDestroy()之前将后退按钮listenerNotified打印到控制台上,来测试上述应用程序.

Every time I test the above application by first tapping the Click me button and then the back button, listenerNotified is printed to the console before onDestroy().

但是我不确定我是否可以依靠这种行为. Android是否可以保证上述情况?我可以安全地假设我的Runnable总是在onDestroy()之前执行,还是有一种情况并非如此?在我的真实应用程序中,当然还有很多事情发生(例如其他线程发布到主线程中以及回调中发生了更多操作).但是,这个简单的代码片段似乎足以证明我的关注.

I'm however not sure if I can rely on this behavior. Does Android make any guarantees about the above scenario? Can I safely assume that my Runnable will always be executed before onDestroy() or is there a scenario where that won't be the case? In my real app, there is of course a lot more happening (like other threads posting to the main thread and more operations happening in the callback). But this simple snippet seemed sufficient to demonstrate my concern.

我是否有可能(可能由于其他线程或发布到主线程的回调的影响)在下面获得调试输出?

Is it every possible (possibly due to the influence of other threads or callbacks posted to the main thread) that I get the debug output below?

D/TAG: onDestroy
D/TAG: listenerNotified

我想知道这一点,因为可能的结果可以解释这次崩溃.

I would like to know this, since that outcome being possible would explain the crash.

推荐答案

是否可以在onDestroy()之后调用回调方法?

Is it possible for a callback method to be called after onDestroy()?

是的

让我们稍微更改一下有关将Runnable发布到Handler的示例代码.我还假设(根据您的描述)您可能在主线程中发布了多个Runnable,因此在某些时候可能会有一个Runnable队列,这使我在下面的实验中有所延迟:

Let's change a bit your sample code regarding posting a Runnable to the Handler. I also assume (according to your description) that you may have multiple Runnables posted to the main thread, so at some point there might be a queue of Runnables which brings me to a delay in the experiment below:

public void onClick(View view) {
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            // This is the callback method
            Log.d("TAG", "listenerNotified");
        }
    }, 3000);
}

现在按按钮b,然后按返回按钮,您应该看到有问题的输出.

Now push the button b, then press the back button and you should see the output in question.

Might it be the reason of your app crash? 很难不说就知道.我只想指出,在线程(在您的情况下为主线程)上实例化new Handler()时,Handler与该线程的Looper消息队列相关联,发送并处理Runnable和来自队列的消息.这些Runnable和消息具有对目标Handler的引用.即使ActivityonDestroy()方法不是析构函数",即,当该方法返回Activity的实例时,也不会立即被杀死(

Might it be the reason of your app crash? It's hard to say without seeing what you got. I'd just like to note that when new Handler() is instantiated on a thread (the main thread in your case), the Handler is associated with the Looper's message queue of the thread, sending to and processing Runnables and messages from the queue. Those Runnables and messages have a reference to the target Handler. Even though Activity's onDestroy() method isn't a "destructor", i.e. when the method returns the Activity's instance won't be immediately killed (see), the memory cannot be GC-ed because of the implicit reference* to the Activity. You'll be leaking until the Runnable will be de-queued from the Looper's message queue and processed.

更详细的解释可以在如何找到泄漏上下文:处理程序和内部类

*匿名内部类Runnable的实例具有对匿名内部类View.OnClickListener的实例的引用,而该实例又引用了Activity实例.

* Instance of anonymous inner class Runnable has a refers to an instance of anonymous inner class View.OnClickListener that, in its turn, has a reference to the Activity instance.

这篇关于是否可以在onDestroy之后调用回调方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆