何时注册/注销活动中创建的广播接收器?


79

我需要在活动的onCreate事件中创建自定义广播接收器,并且显然我需要在活动的onDestroy事件中取消注册广播接收器

为了清楚起见,这是我使用的代码的一部分

public class AnActivity extends Activity {
    private ResponseReceiver receiver;

    public class ResponseReceiver extends BroadcastReceiver {
           public static final String ACTION_RESP =
              "mypackagename.intent.action.MESSAGE_PROCESSED";

           @Override
            public void onReceive(Context context, Intent intent) {
// TODO Start a dialogue if message indicates successfully posted to server
            }
    }   

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        receiver = new ResponseReceiver();
        registerReceiver(receiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

我已经阅读到该活动的onPause / onResume和onStart / onStop事件也应该注册和注销广播接收器。

我真的很想了解什么是最佳实践,为什么。


这是因为在onDestroy()调用when时,接收者将不再监听事件。
de_billa_

Answers:


91

您应该注册和注销注册接收者onStart()onStop()

活动注册BroadcastReceivers的唯一原因是在当前活动上以某种方式使用事件,以将事件通知用户。如果onStop()已被调用,则Activity不再位于前台,因此无法更新用户。

如果要在后台接收广播事件,则应考虑使用此处指示的服务。

就像康斯坦丁(Konstantin)所说的那样,onDestroy()不能保证会被调用,当Activity不再打开时,您可以长时间接收广播。


3
您是否建议我在onCreate的onResume INSTEAD上注册以及?创建活动时是否总是调用onResume?
jamesc 2011年

9
您应该注册onResume是的,如果仅注册onCreate,则始终在显示的活动上调用onResume()(这是活动出现之前的最后一个调用的方法(developer.android.com/reference/android/app/Activity.html)。 ()并取消注册onPause(),然后下次将活动转入前台时,将不会再次调用onCreate(),也不会再次注册接收者。是的,我的意思是INSTEAD,请不要在onCreate上进行操作()
。– SnowyTracks

1
@SnowyTracks:您能否评论为什么最好在onResume / onPause而不是onStart / onStop上执行BroadcastReceiver注册调用?查看绑定服务的开发人员指南,我发现了这一点。在本节末尾,建议出于性能考虑,在onStart / onStop中而不是onResume / onPause中执行服务绑定/取消绑定。我想知道这是否也适用于BroadcastReceivers?提前致谢。
Janus Varmarken 2014年

1
@jvmk同意,Android文档说要在onStart和onStop中执行此操作,我认为在99%的情况下,它几乎没有什么区别,仅行为上的区别是对话框活动或使用了部分前台活动。但我会更新我的答案是在与Android DOC线
SnowyTracks

1
我看到您昨天编辑了第二段...感谢您做出更加一致的回答。但这仍然无法解释为什么应该使用onStart / onStop而不是onResume / onPause或与onResume / onPause结合使用,这是OP的问题。相反,第二段的解释对onResume / onPause同样适用,对onStart / onStop也是如此:一旦调用onPause,活动便不再处于前台。因此,我们没有为您推荐的理由。
LarsH

19

由于onDestroy()不保证被称为您应使用onPause()注销。考虑广播接收机的生命周期:仅当活动处于前台时,才需要将其激活吗?然后使用onResume()/onPause()


如果即使活动处于后台,我们仍然需要更新活动中的内容怎么办,因为用户可以恢复应用程序,并且在这种情况下应显示更新的数据?
Usman Rana

9

Android文档并没有规定注册/注销广播接收器的唯一位置,但同时提到onStart()/onStop()onResume()/onPause()作为可能。

做出此决定的最大因素是,您的接收器何时需要能够执行其工作?这将确定何时注册和注销。

  • 接收者是否仅在关注活动时才需要对广播做些事情?如果是这样,您可以在onPause()/中进行注册/注销onReceive()。(您也可以使用更长的生命期,例如onStart()/ onStop(),但是随后您应该在接收者的onReceive()活动期间检查活动是否聚焦。)

  • 即使接收器没有聚焦,接收器是否需要做一些事情(例如,当显示对话框时)?如果是这样,请使用onStart()/ onStop()(或更长的寿命,但是请再次由接收者onReceive()检查该活动是否可见)。

  • 即使活动不可见,接收方是否也需要了解广播?例如,它需要记住事情发生,这样,当活动变得可见,它可以反映所产生的势态?然后,您需要使用onCreate()/onDestroy()进行注册/注销。(请注意,还有其他方法可以实现这种功能。)

如果您在中注册onStart(),也不要在中注册它们onResume(),因为那将是多余的:onResume()除非先onStart()被调用,否则永远不会调用它。

另外请记住,最好保持onPause()尽可能轻

onPause()的执行非常简短,不一定提供足够的时间来执行保存操作。因此,您不应使用onPause()保存应用程序或用户数据,进行网络调用或执行数据库事务。在该方法完成之前,此类工作可能无法完成。相反,您应该在onStop()期间执行重负载关闭操作。

的确,如果系统为了节省内存而终止您的进程,onDestroy()不能保证会调用调用。但是,如果该进程被终止,则该进程无论如何都不会接收广播。在那种情况下,真的有必要注销广播接收器吗?


感谢您对我的问题的回答,但您的回答令人困惑且不完全准确您说If you register in onStart(), don't also register them in onPause(), because that would be redundant: onPause() is never called without onStart() being called first.的只是不合逻辑且令人困惑,尤其是当接受的答案非常准确时。
jamesc

@jamesc:糟糕,我的意思是onResume而不是onPause。没错,这有点令人困惑。立即修复。至于被接受的答案,我已经对此发表了评论。我相信此答案会添加重要的和相关的信息,而这些信息是被接受的人无法提供的。
LarsH

5

Android可以通过省略onStop()方法杀死您的应用程序。解决这种情况的最好方法是BroadcastReceiveronResume()方法中注册,然后在中注销onPause()


1
我也是。有问题与onStop()藏汉
Vygintas乙

0

您应该在onResume()和onPause()方法中注册和注销广播。

如果您在onStart()中注册并在onStop()中注销。到时候你会得到以下问题。

如果您的设备屏幕处于锁定状态,那么将调用onStop()时间,并且如果您解锁该时间,则永远不会调用onStart()。这就是为什么您要在onResume()和onPause()方法中进行注册和注销的原因。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.