5

我目前正在开发一个具有以下需求的 Android 应用程序:

在服务中启动的工作线程。该线程做了一些处理,需要从主Activity调用,并为同一个Activity提供一些异步应答。

从 Activity 调用服务很容易(IBinder 的东西)

我现在的问题是关于服务回调的正确实现。

我首先要在 Activity 中添加一个 android.os.Handler 并在 MyActivity.handleMessage(Message) 中处理线程的答案,但这需要我将此处理程序的引用提供给服务。那么当 Android 操作系统由于方向改变而决定销毁/重新创建我的 Activity 时会发生什么?我的活动是否在服务中被(间接)引用时保持活跃?如果 Activity 无论如何都销毁/重建,我的 Handler 在 Service 引用会发生什么?

我想我没有使用正确的方法从服务线程回调活动,所以我想知道是否有人可以指出我正确的做法。

TIA

4

4 回答 4

4

我更喜欢使用LocalBroadcastManager

这是您的代码示例Activity

BroadcastReceiver localBroadcastReceiver = new BroadcastReceiver()
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Log.d("BroadcastReceiver", "Message received " + intent.getAction());
        Log.d("BroadcaseReceiver", "Received data " + intent.getStringExtra("com.my.package.intent.EXTRA_DATA"));
    }
};

@Override
protected void onStart()
{
    super.onStart();
    final LocalBroadcastManager localBroadcastManager =
        LocalBroadcastManager.getInstance(this);
    final IntentFilter localFilter = new IntentFilter();
    localFilter.addAction("com.my.package.intent.ACTION_NAME_HERE");
    localBroadcastManager.registerReceiver(localBroadcastReceiver, localFilter);
}

@Override
protected void onStop()
{
    super.onStop();
    final LocalBroadcastManager localBroadcastManager =
        LocalBroadcastManager.getInstance(this);
    // Make sure to unregister!!
    localBroadcastManager.unregisterReceiver(localBroadcastReceiver);
}

代码库中的任何其他地方(例如在后台线程的完成中):

final LocalBroadcastManager localBroadcastManager =
    LocalBroadcastManager.getInstance(context);
final Intent intent = new Intent("com.my.package.intent.ACTION_NAME_HERE")
intent.putExtra("com.my.package.intent.EXTRA_DATA", yourBackgroundData);
localBroadcastManager.sendBroadcast(intent);

当然,您可以使用intent.putExtra添加任何附加数据或使用多个操作来区分广播消息。

于 2013-03-14T15:53:00.847 回答
3

我们通过集中Application课堂中活动和服务之间的所有通信来做到这一点。我们扩展了这个Application类,然后在那里有绑定到服务并接受回调的方法。在此架构中,anActivity和 the之间没有直接联系。Service

这种机制的优点是您不必担心在活动转换和活动死亡和重新活动期间解除绑定/重新绑定到服务。班级管理所有这些Application,并且不受活动的影响。该类Application接收所有回调,您将需要有代码来确定如何处理回调。可能您希望在Application类中存储一些数据,然后通知活动有新数据可用,或类似的东西。

另一种方法是Service广播回调。在这种情况下,服务和活动之间的耦合是松散的,因此您不需要Handler在活动中创建 a 然后将其传递给Service. 活动可以只BroadcastReceiver为他们感兴趣的回调注册 s,或者您可以在清单中管理它。

于 2013-03-14T16:05:41.590 回答
0

正如您所说,一种解决方案是使用 MyActivity.handleMessage(Message)。每当您的活动开始(或重新启动)时,您可能会尝试启动服务(您提到的“onBind”内容)。如果服务已经在运行,则不会造成任何损害。绑定内容完成后,您告诉 Messenger 发送回复的服务。

为确保处理重新启动,在 onStop 中,您需要告诉服务将该 Messenger 从其“发送回复的位置列表”中删除,这样它就不会意外地向现在不存在的 Messenger 发送消息。当 onStart 作为重启的一部分被调用时,它将发送现在正确的 Messenger。

显然,这需要服务处理这个问题,并以某种方式管理它有一个响应要发送而没有 Messenger 可以发送到的场景。它要么保留信息直到 Messenger 可用,要么丢弃信息,并且 Activity 显式获取所有状态信息,作为它在 onStart 中完成的绑定内容的后续。

另一种方法是让 Activity 每隔一段时间(10 秒?)轮询一次服务,当它知道正在进行处理以查看结果是否可用时,然后在所有信息返回后停止轮询。

于 2013-03-14T15:48:27.897 回答
0

对于异步服务调用,我会说,在启动它时会传递一个回调引用。

回调将由绑定线程执行,这是此方法的标准。

当然,发起调用的Activity可以依赖binder线程运行在自己的进程中这一事实。所以很容易从回调中回到主/UI线程。

因此,如果回调需要在主/UI线程中处理某些东西,它只使用

(new Handler(Looper.getMainLooper()).post()

它的优点是它在代码执行的时间点动态地找到主/ UI线程。另一方面,这甚至不是必需的,因为主/UI 线程不会改变,因此通过 View 引用或您在回调中可能手头的任何其他内容也可以找到它。

于 2013-03-14T15:50:48.660 回答