如果通过Bundle作为Parcelable传递,那么Android ResultReceiver回调如何工作?

时间:2014-05-23 06:47:12

标签: android callback parcelable

我已将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方法?

1 个答案:

答案 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();
    }
}