Android startActivityForResult的模拟服务
尽管如此,我有不同的情况: 我的应用程序主要由后台Android startActivityForResult的模拟服务,android,Android,尽管如此,我有不同的情况: 我的应用程序主要由后台服务组成。我想开始外部活动并获得结果 我看到几个选择: 创建虚拟活动并保留对其的引用,以便使用其startActivityForResult。正如我们所知,这会消耗大量内存 使用广播意图代替Android的结果基础设施:要求客户端活动在结束前广播其结果。这种方式打破了这种想法,而且性能效率不高 直接使用检测尝试将startActivityForResult中的代码复制到我的服务中 使用服务接口-序列化并将AIDL连接添加到启动活动的意图。在这种情
服务
组成。我想开始外部活动并获得结果
我看到几个选择:
活动
并保留对其的引用,以便使用其startActivityForResult
。正如我们所知,这会消耗大量内存广播意图
代替Android的结果基础设施:要求客户端活动在结束前广播其结果。这种方式打破了这种想法,而且性能效率不高检测
尝试将startActivityForResult中的代码复制到我的服务中AIDL
连接添加到启动活动的意图。在这种情况下,活动不应该提供结果也许你还有其他想法吗?我认为选项2是android上最惯用的方式。从
活动中使用startActivityForResult
是一个同步/阻塞调用,即父活动等待并且在子活动完成之前不执行任何操作。当从服务
工作并与活动交互时,您主要执行异步/非阻塞调用,即服务调用一些要完成的工作,然后等待信号通知它可以继续
如果您正在使用,则可以让您的活动获取服务的引用
,然后在其执行工作后调用特定函数。尝试您的选项3将与框架为您提供的内容背道而驰 我最近在实施三条腿授权流程时一直在考虑这一点。将结果发送回服务进行处理比在“活动”中处理效果更好。它还提供了更好的关注点分离
虽然没有明确的文档记录,但Android提供了一种简单的方式,可以在任何地方(包括服务)发送和接收结果
我发现它比传递活动要干净得多,因为这总是伴随着泄露这些活动的风险。此外,调用具体方法的灵活性较低
要在服务中使用ResultReceiver
,您需要对其进行子类化,并提供一种处理收到的结果的方法,通常在内部类中:
public class SomeService extends Service {
/**
* Code for a successful result, mirrors {@link Activity.RESULT_OK}.
*/
public static final int RESULT_OK = -1;
/**
* Key used in the intent extras for the result receiver.
*/
public static final String KEY_RECEIVER = "KEY_RECEIVER";
/**
* Key used in the result bundle for the message.
*/
public static final String KEY_MESSAGE = "KEY_MESSAGE";
// ...
/**
* Used by an activity to send a result back to our service.
*/
class MessageReceiver extends ResultReceiver {
public MessageReceiver() {
// Pass in a handler or null if you don't care about the thread
// on which your code is executed.
super(null);
}
/**
* Called when there's a result available.
*/
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Define and handle your own result codes
if (resultCode != RESULT_OK) {
return;
}
// Let's assume that a successful result includes a message.
String message = resultData.getString(KEY_MESSAGE);
// Now you can do something with it.
}
}
}
在服务中启动活动时,创建结果接收器并将其打包到intent extras中:
/**
* Starts an activity for retrieving a message.
*/
private void startMessageActivity() {
Intent intent = new Intent(this, MessageActivity.class);
// Pack the parcelable receiver into the intent extras so the
// activity can access it.
intent.putExtra(KEY_RECEIVER, new MessageReceiver());
startActivity(intent);
}
最后,在活动中,打开接收器的包装,并使用ResultReceiver#send(int,Bundle)
将结果发回
您可以随时发送结果,但我选择在完成之前发送:
public class MessageActivity extends Activity {
// ...
@Override
public void finish() {
// Unpack the receiver.
ResultReceiver receiver =
getIntent().getParcelableExtra(SomeService.KEY_RECEIVER);
Bundle resultData = new Bundle();
resultData.putString(SomeService.KEY_MESSAGE, "Hello world!");
receiver.send(SomeService.RESULT_OK, resultData);
super.finish();
}
}
谢谢你的想法!现在我在2(更容易实现)和4(更安全/更私密,应该更快)之间进行选择。我真的不同意startActivityForResult是阻塞的(因为它使用回调函数,而不是结果值),而且插装在公共API=)中,谢谢!我的意思是它不是传统意义上的阻塞(例如,阻塞io调用)。它是以您使用它的概念性方式阻塞的。@Qberticus您提供的链接只是指向通用示例页面的链接。它可以通过使用SharedReferences进行简单的破解来实现,谢谢您的解决方案!有一件事:根据Activity.javaGood point,RESULT_OK应该是-1。我认为在这种情况下,可以使用任何值,但最好与平台提供的内容保持一致。我已经更新了答案。您也可以直接使用Activity.RESULT\u OK。您需要在类MessageReceiver
之前添加@suppressint(“ParcelCreator”)
,否则它会要求您将创建者设置为可包裹。谢谢你的回答。