zoukankan      html  css  js  c++  java
  • 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




  • 相关阅读:
    python json模块出现Invalid control character这个异常的原因
    KMS服务,使用命令激活windows/office
    vscode Python文件头部信息
    MIMIC-III Clinical Database 翻译
    autohotkey 设置
    DeepLearning 写代码常用
    VScode 个人设置
    随机种子设置
    samba配置
    jieba 分词不显示日志
  • 原文地址:https://www.cnblogs.com/younghome/p/6804399.html
Copyright © 2011-2022 走看看