Android实现组件之间同步的回调通信

        Android开发中,有时会遇到组件之间相互通信回调的问题。一般都是通过Android提供的ResultReceiver来实现(ResultReceiver的使用方法很简单,这里就不多提了)。

        但之前在工作中,遇到了一个组件间回调的问题,ResultReceiver无法满足需求。简单描述一下问题:service中打开了一个activity,activity需要将一个变量值回调给service,而且这个回调必须是同步的。也就是说activity在确认service接收到了这个变量值后,才能继续向下执行代码。众所周知ResultReceiver的send方法是异步的,send方法执行后,接收方可能还没有收到消息。这样"不及时"的回调在我的项目中可能会造成状态不同步。

        那么,只能自己实现一个同步的回调通信。

 

        同步的回调通信代码如下:

        github地址:https://github.com/yuhaiyang89/yhy-utils

 

1.定义一个AIDL

package com.yhy.utils;
interface IChannel {
     void send(int code, in Bundle data);
}

2.定义一个类,实现Parcelable(实现Parcelable是为了能让该类在组件中传递),并在此类中实现第一步定义的AIDL(通过这个AIDL完成回调)

package com.yhy.utils.demo;

import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import com.yhy.utils.IChannel;

public class SyncResultReceiver implements Parcelable {
    
    public static final Parcelable.Creator<SyncResultReceiver> CREATOR = new Parcelable.Creator<SyncResultReceiver>() {
        
        public SyncResultReceiver createFromParcel(Parcel in) {
            return new SyncResultReceiver(in);
        }

        public SyncResultReceiver[] newArray(int size) {
            return new SyncResultReceiver[size];
        }
    };
    
    // 是本地回调还是远程回调
    final boolean mLocal;

    IChannel mBridge;


    public SyncResultReceiver() {
        mLocal = true;
    }

    SyncResultReceiver(Parcel in) {
        mLocal = false;
        mBridge = IChannel.Stub.asInterface(in.readStrongBinder());
    }

    public void send(int code, Bundle data) {
        if (mLocal) {
            onReceiveResult(code, data);
            return;
        }

        if (mBridge != null) {
            try {
                mBridge.send(code, data);
            } catch (Exception e) {
                Log.e("", "",e);
            }
        }
    }

    protected void onReceiveResult(int code, Bundle bundle) {
        // 等待子类去实现此方法,接收消息
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel out, int flags) {
        synchronized (this) {
            if (mBridge == null) {
                mBridge = new MyChannel();
            }
            out.writeStrongBinder(mBridge.asBinder());
        }
    }

    class MyChannel extends IChannel.Stub {
        public void send(int code, Bundle data) {
            onReceiveResult(code, data);
        }
    }
}

实现完毕!

 

下面就可以使用SyncResultReceiver来实现同步回调了

例:MainActivity中打开Activity2,Activity2将一些消息同步的回调给MainActivity

MainActivity代码:

package com.yhy.utils.demo;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private int value = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 重写SyncResultReceiver的onReceiveResult方法接收返回值
        SyncResultReceiver mResultReceiver = new SyncResultReceiver(){
            @Override
            protected void onReceiveResult(int code, Bundle bundle) {

                value = bundle.getInt("value");
                Log.d("TEST", "code=" + code + " | value = " + value);
            }
        };

        // 开启Activity2
        Intent intent = new Intent(this, Activity2.class);
        intent.putExtra("callback", mResultReceiver);
        startActivity(intent);
    }
}

Activity2代码:

package com.yhy.utils.demo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class Activity2 extends AppCompatActivity {

    SyncResultReceiver mReceiver = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReceiver = getIntent().getParcelableExtra("callback");

        // 给MainActivity回调值
        Bundle bundle = new Bundle();
        bundle.putInt("value", 1);
        mReceiver.send(1, bundle);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 给MainActivity回调值
        Bundle bundle = new Bundle();
        bundle.putInt("value", 2);
        mReceiver.send(1, bundle);
    }

    @Override
    protected void onDestroy() {
        // 给MainActivity回调值
        Bundle bundle = new Bundle();
        bundle.putInt("value", 3);
        mReceiver.send(1, bundle);
        super.onDestroy();
    }
}

 

LOG输出:

03-03 11:50:28.780 2790-2790/? D/TEST: code=1 | value = 1
03-03 11:50:28.782 2790-2790/? D/TEST: code=1 | value = 2
03-03 11:53:07.588 2790-2790/? D/TEST: code=1 | value = 3




posted @ 2017-05-03 22:40  神奇的洋葱  阅读(1338)  评论(0编辑  收藏  举报