将变量从onHandleIntent()传递给应用程序Singleton时的“竞争条件”

时间:2013-12-11 22:53:36

标签: android android-intent singleton global-variables intentservice

我刚刚开始学习android编程,当我在IntentService(onHandleIntent方法)中将一个复杂变量“solve”传递回主Activity时,我遇到了多次迭代。除了我的(正在运行的应用程序)之外,我不打算将这些数据提供给其他应用程序。

首先,我将Serializable实现为我的复杂数据,然后将其作为额外内容传递给通过BroadcastReceiver方法发送回主Activity的Intent。这是在 onHandleIntent 方法实现中完成的,如果我理解正确,它将在另一个线程上运行(不会占用主线程)。

    Log.d(LOG_TAG, "Sending action update ready...");

    Intent i = new Intent(ACTION_UPDATE_READY);
    // Intent extra begin
    i.putExtra("the_complex_data", complexSerializableData);
    // Intent extra end
    LocalBroadcastManager.getInstance(this).sendBroadcast(i);

在主Activity中,接收器设置如下:

private BroadcastReceiver onUpdate = new BroadcastReceiver() {
 public void onReceive(Context ctxt, Intent i) {

    Log.d(LOG_TAG, "Receiving ACTION_UPDATE_READY");

    Bundle extras = i.getExtras();
    if (extras != null) {
        ComplexData data = (ComplexData) extras.getSerializable("the_complex_data");
        if (data != null && data.size() > 0) {
            updateAvailable(data); // refresh GUI
        } else {
            Toast.makeText(ctxt, "Connection is bad", Toast.LENGTH_LONG).show();
        }
    }


 }
};

后来,我发现Parceable会比Serializable产生更好的性能,正如你在SO中的大多数讨论中所发现的那样。

然后又在谷歌搜索之后,我发现这个topic就在developer.android.com上,说明你可以使用Singleton来传递东西!

所以我为我的应用程序创建了一个单例类,这样它就可以保存一个变量,我可以在onHandleIntent方法中将结果“存储”到这个变量,然后在我的主Activity中检索它,收到广播。

基本上,我不再需要传递Extra,而是更改它以在应用程序范围的Singleton(mAppGlobals)中设置变量:

mAppGlobals.setSharedData(complexSerializableData);

然后像以前一样发送广播。

在主Activity的BroadcastReceiver上,我没有从收到的Intent extra中提取数据,而只是从Singleton中抓取数据:

ComplexData data = mAppGlobals.getSharedData();

在此更改之后,它似乎在模拟器上工作(仍然)。但是,我不确定是否会发生,其中我的主要活动中的广播接收器代码将获取“旧数据”,因为在另一个线程上运行的“onHandleIntent”尚未完成写入Singleton实例变量(通过setSharedData方法)。

android框架是否“确保”当BroadcastReceiver代码在我的主Activity上执行时,在后台线程(IntentService)上运行的“onHandleIntent”方法实际上写完了我的全局Singleton变量?

1 个答案:

答案 0 :(得分:0)

首先,我建议不要使用中间单例,只是为了在两个类之间传递数据。特别是当已经有一种内置方法仅仅是为了这个目的。使用静态类来维护应用程序中的数据非常有用,但根据经验,除非必须从应用程序中的多个点访问数据,否则不要将数据放在那里。

要解决并发问题,只要服务在发送消息之前设置数据,并且仅在收到消息后才访问数据,那么您将没有竞争条件。请注意,您在代码中构建了许多隐含的假设,这也是一件好事。如果其他人要查看您的代码,他们怎么知道在收到邮件之前您不能访问数据?

更常见的解决方案是使用锁。在这种情况下,当一个线程访问你的数据变量时,它将被授予对它的唯一访问权,直到该线程释放锁。这将阻止任何其他线程访问数据,直到原始线程释放它的锁定。请注意,如果被阻止的线程是UI线程,这种阻塞可能会导致应用程序断断续续或停止(Android无响应)。这只是你应该通过意图传递数据的另一个原因。

话虽如此,我认为您在很多方面重新实现数据处理非常棒,因为它可以为您提供有关不同选项的宝贵视角。