Android静态变量的服务与活动不同

时间:2013-06-21 15:52:36

标签: android multithreading android-service classloader

我希望有人可以清楚我的代码中发生的事情。我有一个代码块读取和写入我的数据库,它从服务和我的活动运行。我需要这个代码块是线程安全的,无论它是从服务还是活动调用。因此,我接受了代码块所在的类,并创建了一个静态锁定对象,以保持线程安全,如下面的代码块所示:

synchronized(AnalyticsMessages.sync_lock){
                Log.v("mixpanel", "locking off of: "+AnalyticsMessages.sync_lock.toString());
                String[] eventsData = mDbAdapter.generateDataString(table);
                if (eventsData != null) {
                    String lastId = eventsData[0];
                    String rawMessage = eventsData[1];
                    HttpPoster poster = getPoster(mEndpointHost, mFallbackHost);
                    HttpPoster.PostResult eventsPosted = poster.postData(rawMessage, endpointUrl);

                    if (eventsPosted == HttpPoster.PostResult.SUCCEEDED) {
                        logAboutMessageToMixpanel("Posted to " + endpointUrl);
                        logAboutMessageToMixpanel("Sent Message\n" + rawMessage);
                        //Log.v("mixpanel", "Sent Message\n" + rawMessage);
                        mDbAdapter.cleanupEvents(lastId, table);
                        Log.v("mixpanel", "removing id: "+lastId);
                    }
                    else if (eventsPosted == HttpPoster.PostResult.FAILED_RECOVERABLE) {
                        // Try again later
                        if (!hasMessages(FLUSH_QUEUE)) {
                            sendEmptyMessageDelayed(FLUSH_QUEUE, mFlushInterval);
                        }
                    }
                    else { // give up, we have an unrecoverable failure.
                        mDbAdapter.cleanupEvents(lastId, table);
                    }
                }
            }

sync_lock在AnalyticsMessages中定义,如下所示:

private static final Object sync_lock = new Object();

显然没有正确锁定,因此带有toString的日志。日志告诉我,我似乎有两个不同的sync_lock变量(因为它在内存中打印一个地址)。我应该提一下,AnalyticsMessages实例化如下:

public static AnalyticsMessages getInstance(Context messageContext) {
    synchronized (sInstances) {
        Context appContext = messageContext.getApplicationContext();
        AnalyticsMessages ret;
        if (! sInstances.containsKey(appContext)) {
            if (MPConfig.DEBUG) Log.d(LOGTAG, "Constructing new AnalyticsMessages for Context " + appContext);
            ret = new AnalyticsMessages(appContext);
            sInstances.put(appContext, ret);
        }
        else {
            if (MPConfig.DEBUG) Log.d(LOGTAG, "AnalyticsMessages for Context " + appContext + " already exists- returning");
            ret = sInstances.get(appContext);
        }
        return ret;
    }
}

似乎正在发生的事情是,当服务将自己作为上下文传递给AnalyticsMessages.getInstance时,我最终会得到一个sync_lock变量,但是当我的一个活动将其自身作为上下文传递时,我最终会得到一个不同的一个?这是否意味着android服务使用与主进程不同的类加载器?有解决方法吗?我认为这实际上是一个相对常见的问题?我完全偏离了这里发生的事情吗?提前谢谢!

1 个答案:

答案 0 :(得分:2)

  

似乎android:process用于我的后台服务

这是这个特定困难的常见原因。虽然从Java源的角度来看,它只是一个应用程序,但是您运行两个单独的进程这意味着您有两个单独的对象堆,因此一个堆中的全局(静态数据成员)将不同于 - 在另一个堆中命名为global。

  

是否有充分理由让服务在与应用程序其余部分不同的进程中运行?

通常不是。它会导致您的应用程序占用更多内存和更多CPU时间,并限制各种组件(在不同进程中运行)进行互操作的能力,如您所见。我通常会反对多个流程。话虽这么说,改变它将保证彻底的测试,特别是如果你不知道为什么首先使用这种技术。