Android:即使我调用了 unregisterReceiver,也会抛出 Leaked IntentReceiver 异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3577566/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:49:55  来源:igfitidea点击:

Android: Leaked IntentReceiver exception is being thrown even though I call unregisterReceiver

androidexception

提问by Doug Miller

I don't understand why I'm getting this exception when hitting the back button. I have the IntentReceiver registered in the onCreate method and it is supposed to be unregistered in the onPause method. My Log.w() call inside of the onPause method leads me to believe that the unregisterReceiver() method is being called, but I am getting this exception still.

我不明白为什么我在点击后退按钮时会收到这个异常。我在 onCreate 方法中注册了 IntentReceiver 并且它应该在 onPause 方法中取消注册。我在 onPause 方法中调用 Log.w() 使我相信正在调用 unregisterReceiver() 方法,但我仍然收到此异常。

Any thoughts?

有什么想法吗?

private PlayerReceiver playerReceiver;

public void onCreate(Bundle savedInstanceState) {
 ...
     IntentFilter playerFilter;     
     playerReceiver = new PlayerReceiver();
     playerFilter = new IntentFilter(PlayerService.BUFFERING_FAILURE);
     playerFilter.addAction(PlayerService.BUFFERING_SUCCESS);
     registerReceiver(playerReceiver, playerFilter);
 ...
}

protected void onPause() {
 ...
     if (playerReceiver != null){
         unregisterReceiver(playerReceiver);
         Log.w(TAG, "playerReceiver has been unregistered");
         playerReceiver = null;
     }
 ...
}

public class PlayerReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(PlayerService.BUFFERING_FAILURE)){
            setListenButton(false);
        }
        closePlayDialog();
    }
}

LogCat Output

LogCat 输出

08-26 11:44:28.646: WARN/WWOZMain(1058): playerReceiver has been unregistered    
08-26 11:44:29.476: ERROR/ActivityThread(1058): Activity org.wwoz.WWOZMain has leaked IntentReceiver org.wwoz.WWOZMain$PlayerReceiver@43e4dd60 that was originally registered here. Are you missing a call to unregisterReceiver()?    
08-26 11:44:29.476: ERROR/ActivityThread(1058): android.app.IntentReceiverLeaked: Activity org.wwoz.WWOZMain has leaked IntentReceiver org.wwoz.WWOZMain$PlayerReceiver@43e4dd60 that was original

ly registered here. Are you missing a call to unregisterReceiver()?

在这里注册。您是否错过了对 unregisterReceiver() 的调用?

回答by peter_pilgrim

This is a Android activity life cycle issue. I am seeing it in a main activity and then testing on device with the back button that goes back to a splash screen.

这是一个 Android 活动生命周期问题。我在主要活动中看到它,然后使用返回启动屏幕的后退按钮在设备上进行测试。

In the onPause()method.

onPause()方法中。

Unregister the BroadcastReceiverthat you created in the onCreate()

取消注册BroadcastReceiver您在onCreate()

In the onRestart()re-register a brand new Broadcast Receiver.

onRestart()重新注册一个全新的广播接收器。

In the activity class you need to keep a record of the Broadcast Receiver as instance data member.

在活动类中,您需要将广播接收器的记录作为实例数据成员。

SECOND

第二

I think this also a feature enhancement issue with Android.

我认为这也是 Android 的一个功能增强问题。

Sometimes developer need a broadcast receiver to outlive the activity. For example to understand when certain screen states are available or not. Think about a conversation context of work flow model, which has many states.

有时开发人员需要一个广播接收器来超过活动。例如,了解某些屏幕状态何时可用。考虑工作流模型的对话上下文,它有许多状态。

THIRD

第三

You can register and unregister broadcast receivers with an activity, but a simple call like isRegistered(BroadcastReceiver)in the Activity class might be very useful.

您可以使用活动注册和取消注册广播接收器,但像isRegistered(BroadcastReceiver)Activity 类中的简单调用可能非常有用。

If you need receivers to live beyond the activity, then I do not the answer, except to silence the warning, by adding unregister(X)in the onDestroy()call. YMMV ;-)

如果需要接收器之外直播活动,那么我不回答,只是沉默的警告,加入unregister(X)onDestroy()呼叫。YMMV ;-)

回答by Mullins

I had the exact same problem. The cause was that I had inadvertently registered the same BroadcastReceiver twice.

我有同样的问题。原因是我无意中注册了同一个 BroadcastReceiver 两次。

回答by Weekend

My situation was similar with Mullins, I registered a receiver in both a class and its subclass.

我的情况和 Mullins 类似,我在一个类和它的子类中都注册了一个接收器。

For newbies like me, just toggle a breakpoint at your receiver, then debug your application. If the receiver is something like com.example.main.listener.MyRecevier@421c0100, while the error log in logcat is different from it, such as com.example.main.listener.MyRecevier@4202fb40, with characters after "@" different, surely you registered it twice (or more).

对于像我这样的新手,只需在您的 处切换断点receiver,然后调试您的应用程序。如果接收器是类似的com.example.main.listener.MyRecevier@421c0100,而logcat中的错误日志与它不同,例如com.example.main.listener.MyRecevier@4202fb40,“@”后的字符不同,那么您肯定注册了两次(或更多)。

(Above likes a comment under Mullins' answer, actually, I post it here because I can't post comments now.)

(上面喜欢在穆林斯的回答下发表评论,实际上,我把它贴在这里是因为我现在不能发表评论。)