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

dle*_*rob 6 android callback parcelable

我已经从我的Activity传递了ResultReceiver到我的服务.

将ResultReceiver传递给我的服务的活动代码示例,以便服务可以回调Activity:

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);
Run Code Online (Sandbox Code Playgroud)

InstructionService代码示例:

protected void onHandleIntent(Intent intent) {
    Bundle parameters = intent.getExtras();
    ResultReceiver resultReceiver = parameters.getParcelable("receiver");
    resultReceiver.send(METHOD_STATUS_RUNNING, Bundle.EMPTY);
}
Run Code Online (Sandbox Code Playgroud)

现在,这工作正常,因为当我在我的服务中调用resultReceiver.send方法时,会执行活动中相应的onReceiveResult方法.

我的问题是,这是如何工作的?据我所知,ResultReceiver作为Parcelable从活动传递到服务,这意味着它是该对象的"副本",而不是对在Activity中创建的原始ResultReceiver对象的引用.因此,如何对服务类的ResultReceiver的副本发送方法的调用,让这个活动中的原ResultReceiver对象运行它的onReceiveResult方法?

dan*_*117 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();
    }
}
Run Code Online (Sandbox Code Playgroud)