我最近在使用三足授权流程实现 account authenticators 时一直在考虑这个问题。将结果发送回服务进行处理比在活动中处理它执行得更好。它还提供了更好的关注点分离。
没有那么清楚的记录,但 Android 提供了一种简单的方法,可以使用 ResultReceiver 在任何地方(包括服务)发送和接收结果。
我发现它比传递活动要干净得多,因为这总是伴随着泄露这些活动的风险。此外,调用具体方法也不太灵活。
要在服务中使用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.
}
}
}
当您在服务中启动 Activity 时,创建一个结果接收器并将其打包到 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();
}
}