接收异步操作和垃圾回收

5

在onReceive方法中的线程是否有资格在完成之前被垃圾回收?

@Override
public void onReceive(final Context context, Intent intent) {
    final int alarmId = intent.getExtras().getInt(EXTRA_ALARM_ID);
    Log.i(TAG, "/onReceive with an alarmVo.id of " + alarmId);

    // RUN MY THREAD
    new Thread(new Runnable() {
        @Override
        public void run() {
            AlarmUtil.setNextAlarm(context, alarmId);
        }
    }).start();
}

根据我从这里理解:http://developer.android.com/reference/android/content/BroadcastReceiver.html ,似乎是这样,但我并不确定。
“任何需要异步操作的东西都不可用,因为您需要从函数中返回以处理异步操作,但此时BroadcastReceiver已不再运行,因此系统可以在异步操作完成之前杀死其进程。”
如果它被垃圾回收,那么如何解决这个问题?我的方法应该是什么?
1个回答

6
任何通过start()方法启动但尚未完成的线程对象都充当垃圾收集根...直到其run()方法完成,它本身及其强引用的任何内容都不符合垃圾回收的条件。请参见以下答案:
- 没有引用的新线程何时被垃圾回收 - Java线程是否被垃圾回收 编辑:现在您已经向问题添加了额外的上下文,事情变得更加清晰。这种情况与垃圾回收完全不同。对于静态发布的BroadcastReceiver(在应用程序的清单中使用标记定义),Android可以在onReceive(Context,Intent)返回后杀死其进程。您的异步操作不会由于GC而停止,而是由于托管它的进程被Android杀死。
关于你的方法,一切取决于你想要实现什么。如果你想在BroadcastReceiver中执行的代码可以同步运行,那么这将是最简单的方法。我假设这不可能。在这种情况下,文档的this portion似乎适用(重点是我的):(一旦你从onReceive()返回,BroadcastReceiver就不再 active,它的主机进程只有其他正在其中运行的应用程序组件一样重要。这是特别重要的,因为如果该进程只托管BroadcastReceiver(这是用户从未或最近没有与之交互的应用程序的常见情况),则在从onReceive()返回时,系统将认为其进程为空,并积极终止它,以便资源可用于其他更重要的进程。这意味着对于较长时间的操作,你通常会与BroadcastReceiver一起使用Service来保持包含进程在整个操作期间处于活动状态,以使你的异步操作存活足够长的时间来完成。所以,要么同步运行接收器代码,要么使用Service来保持异步操作活动状态,直到完成。
当然,这只适用于在其他情况下处于非活动状态的应用程序中静态注册接收器。如果您从某个其他活动组件(例如Activity)中动态注册它,则该组件可以管理您的异步操作。有关更多信息,请参见this answer

你能进一步解释一下这句话的意思吗:"任何需要进行异步操作的内容都不可用,因为你需要从函数返回以处理异步操作,但此时 BroadcastReceiver 不再处于活动状态,因此系统可以在异步操作完成之前杀死其进程。" - user123321
我现在编辑了我的回答,因为你添加了更多的上下文。希望能有所帮助。 - Michael Sims

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接