我已将ResultReceiver从我的Activity传递给我的服务。
活动代码示例将ResultReceiver传递给我的服务,以便服务可以回调活动:
ResultReceiver receiver = new ResultReceiver(new Handler()) {
protected void onReceiveResult(int resultCode, Bundle resultData) {
//process results
}
}
Intent instructionServiceIntent = new Intent(context, InstructionService.class);
instructionServiceIntent.putExtra("receiver", receiver);
context.startService(instructionServiceIntent);
指令服务代码示例:
protected void onHandleIntent(Intent intent) {
Bundle parameters = intent.getExtras();
ResultReceiver resultReceiver = parameters.getParcelable("receiver");
resultReceiver.send(METHOD_STATUS_RUNNING, Bundle.EMPTY);
}
现在,这工作正常,因为当我在服务中调用resultReceiver.send方法时,会执行活动中相应的onReceiveResult方法。
我的问题是, 这是如何工作的?据我所知,ResultReceiver作为Parcelable从活动传递到服务,这意味着它是一个" copy"该对象的值,而不是对在Activity中创建的原始ResultReceiver对象的引用。因此,如何在服务类的ResultReceiver副本上调用send方法,使得活动中的原始ResultReceiver对象运行它的onReceiveResult方法?
答案 0 :(得分:2)
ResultReciver
实现了Parcelable
,因此可以在意图中传递。
对于startservice,只需加载用于启动服务的意图,就像发送到活动的意图一样,然后在服务进程中加载onStartComand()中的意图数据;
如果要将消息发送回服务,则应绑定到服务startboundservice,并在服务中将onBind()中的处理程序返回给活动。
这就是ResultReceiver的神奇之处。它只是一个预填充处理程序的消息,因此可以序列化并传回。
如果您只想从动态创建的某个片段类中获得回复,或者在规范之外实际上序列化回调,则可以传入填充了将处理该消息的处理程序的消息。
下面我创建一个处理程序,然后使用处理程序创建一条消息。然后我开始一个做一些模糊的片段,最后返回消息。因此,消息只是一个副本,但它实际上是一个在包中传递的回调。
这是新代码,所以我不知道它有多稳定......
public void get_UserEmail(final MyGooglePlayCallback userEmailCallback) {
//handle message gets called when the fragment calls msg.sendToTarget()
//
class JX implements Handler.Callback {
@Override
public boolean handleMessage(Message msg) {
Bundle b = msg.getData();
String s = "";
if (b != null) {
s = b.getString("email");
}
msg.recycle();
userEmailCallback.onComplete(s);
return true;
}
}
JX jx = new JX();
Handler h = new Handler(jx);
final Message msg = Message.obtain(h);
MyGooglePlayCallback cb;
// start the account picker to get the email
String[] accountTypes = new String[]{"com.google"};
Intent intentx = AccountPicker.newChooseAccountIntent(null, null,
accountTypes, false, null, null, null, null);
MyFragmentActivityForResult2 f = MyFragmentActivityForResult2.newInstance(
intentx, REQUEST_CODE_PICK_ACCOUNT, msg);
FragmentTransaction fragmentTransaction = fragManager
.beginTransaction();
fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT);
fragmentTransaction.commit();
}
public static class MyFragmentActivityForResult2 extends Fragment {
private Message msg;
private int requestCode;
private Intent intent;
static MyFragmentActivityForResult2 newInstance(Intent intent, int requestCode,
Message message) {
MyFragmentActivityForResult2 f = new MyFragmentActivityForResult2();
Bundle args = new Bundle();
args.putInt("requestCode", requestCode);
args.putParcelable("message", message);
args.putParcelable("intent", intent);
f.setArguments(args);
return f;
}
MyFragmentActivityForResult2() {
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
Bundle b = this.getArguments();
requestCode = b.getInt("requestCode");
msg = b.getParcelable("message");
intent = b.getParcelable("intent");
startActivityForResult(intent, requestCode);
}
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == this.requestCode) {
String mEmail = "";
if (resultCode == Activity.RESULT_OK) {
mEmail = data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
}
Bundle b = new Bundle();
b.putString("email", mEmail);
msg.setData(b);
msg.arg1 = requestCode;
msg.arg2 = resultCode;
msg.sendToTarget();
}
fragManager.beginTransaction().remove(this).commit();
}
}