Atlas通信方式之——RemoteTransactor

简述:
Atlas提供了3中通讯方式分别是:RemoteTransactor、RemoteView、RemoteFragment.
RemoteTransactor是RemoteView、RemoteFragment 通讯方式的简化版仅仅为了Bundle和Bundle之间的通讯而存在,这篇文章将提供简单的使用实例,和源码简析和指出其中存在的坑。


场景还原
准备:打开开发者选项——》不保留活动 模拟后台页面被回收的场景
测试 :
1.打开应用页面调用顺序 MainActivity ——> ActivityA
2. 点击返回键
正常情况下MainActivity的生命周期会走 onSaveInstanceState,点击返回键后走 onRestoreInstanceState 返回MainActivity页面
诡异现象:
我们发现我们的app并没有这样走,流程这样的 MainActivity的生命周期会走 onSaveInstanceState ——> onDestory——> finish 点击返回键后直接回到了桌面吗,这样的体验不能忍的。


调用实例

   /**
     * 初始化
     *
     * @param activity
     */
    public static void initQbank(Activity activity) {

        RemoteFactory.requestRemote(RemoteTransactor.class, activity, new Intent(BundleIntent.FLAG_QUESTION_BANK),
                new RemoteFactory.OnRemoteStateListener() {
                    @Override
                    public void onRemotePrepared(RemoteTransactor iRemote) {

                        iRemote.call(String.valueOf(SKIP.INIT_ENV), new Bundle(), new IRemoteTransactor.IResponse() {
                            @Override
                            public void OnResponse(Bundle bundle) {

                            }
                        });
                    }

                    @Override
                    public void onFailed(String s) {
                        Log.e("UserRemoteActivity", s);
                    }
                });
    }

出了问题不能怂啊,让我们跟下源码看一下

//参数讲解:
// remoteClass 指定通讯方式
// activity 为了获取 remoteActivity 即 remoteTransactor.remoteActivity
// intent 存储目标bundle的标识
// listener 找到目标bundle后留给我们的回调去做后续的处理
public static <T extends IRemoteContext> void requestRemote(final Class<T> remoteClass,final Activity activity,final Intent intent, final OnRemoteStateListener listener){
         //... 关键代码讲解,可以跟着源码去梳理
         // 获取到目标标识,这个我们在清单文件通过 标签配置过
         final String key = intent.getComponent()!=null ? intent.getComponent().getClassName() :intent.getAction();
         String tempBundleName = null;
         //判断通讯方式
         if(remoteClass == RemoteView.class){
            tempBundleName = AtlasBundleInfoManager.instance().getBundleForRemoteView(key);
        }else if(remoteClass == RemoteTransactor.class){ //这次我们讲解的是这个
            tempBundleName = AtlasBundleInfoManager.instance().getBundleForRemoteTransactor(key);
        }else if(remoteClass == RemoteFragment.class){
            tempBundleName = AtlasBundleInfoManager.instance().getBundleForRemoteFragment(key);
        }
        //获取到目标bundle的name
        final String bundleName = tempBundleName;
         ...
         //获取我们通信类
         RemoteTransactor transactor = RemoteTransactor.crateRemoteTransactor(activity,key,bundleName);
         //回调,在上面实例代码中可以看到
         listener.onRemotePrepared(transactor);
        //...                                                       
}

具体讲解 RemoteTransactor实例的生成

//代码引入
RemoteTransactor transactor = RemoteTransactor.crateRemoteTransactor(activity,key,bundleName);
   public static RemoteTransactor crateRemoteTransactor(Activity activity,String key,String bundleName) throws Exception{
       //创建远程RemoteTransactor 实例
        RemoteTransactor remoteTransactor = new RemoteTransactor();
        //目标bundle的名字
        remoteTransactor.targetBundleName = bundleName;
        //注意这个时候需要用到activity 这个我建议了Atlas团队去掉,这个Activity参数在这里除了引起误会意外并没有其他作用
        if(activity!=null) {
            remoteTransactor.remoteActivity = RemoteActivityManager.obtain(activity).getRemoteHost(remoteTransactor);
        }
        //获取目标bundle的信息
        final BundleListing.BundleInfo bi = AtlasBundleInfoManager.instance().getBundleInfo(bundleName);
        //根据清单文件中的key获取到目标bundle中的目标文件
        String viewClassName = bi.remoteTransactors.get(key);
        //通过反射拿到目标类
        Class transactorClass = Atlas.getInstance().getBundleClassLoader(bundleName).loadClass(viewClassName);
        //创建目标类的实例
        IRemote remote = (IRemote)transactorClass.newInstance();
        //将目标类实例存到remoteTransactor中
        remoteTransactor.targetTransactor = remote;

    //为targetTransactor 的remoteContext赋值
    Util.findFieldFromInterface(remoteTransactor.targetTransactor,"remoteContext").set(remoteTransactor.targetTransactor,remoteTransactor);
    //为targetTransactor 的realHost赋值    Util.findFieldFromInterface(remoteTransactor.targetTransactor,"realHost").set(remoteTransactor.targetTransactor,remoteTransactor.remoteActivity);
   //这两句代码在这种通讯方式中完全没有用,估计是阿里的同学copy的结果,鄙视下不追求整洁
        return remoteTransactor;
    }

好了我们获取到了我们的RemoteTransactor 实例,在上面的实例中我们看到了listener.onRemotePrepared(transactor);回调 这个时候我们就梳理流畅了吧

RemoteTransactor 中的call 方法

   @Override
    public Bundle call(String commandName, Bundle args, IResponse callback) {
        //就是这么回事
        return targetTransactor.call(commandName,args,callback);
    }

调用远端bundle的方法

 @Override
public void onRemotePrepared(RemoteTransactor iRemote) {

 iRemote.call(String.valueOf(SKIP.INIT_ENV), new Bundle(), new IRemoteTransactor.IResponse() {
          @Override
         public void OnResponse(Bundle bundle) {

        }
      });
}

目标类实现IRemote 接口

public class Entrance implements IRemote {
    ...
    @Override
    public Bundle call(String commandName, Bundle args, IResponse callback) {
        int flag = Integer.parseInt(commandName);
        if (flag == LiveSKIP.INIT_ENV) {
            String env = args.getString(Args.ENV);
            initPermission(env);
        } else if (flag == LiveSKIP.RECORD) {
            //回放
            toRecord(ApplicationsHelper.context(), args);
           // testToRecord(ApplicationsHelper.context(), args);
        } else if(flag == LiveSKIP.LIVING) {
            jumpToliving(ApplicationsHelper.context(), args);
        }
        callback.OnResponse(null);
        return null;
    }
}

这算是将RemoteTransactor 这种通讯方式梳理完了,里面还有很多细节,感兴趣的可以再扒源码看看

    Q25:RemoteTransactor 通讯方式引起的问题
 A:如果使用RemoteTransactor 这种通讯方式的话,调用 RemoteFactory.requestRemote 时候最好
 activity 传为null,避免不必要的问题,否则这个activity有可能被finish掉引起一些奇怪的现象

这个在Atlas外部交流群中我已经提出来了并写在了小喇叭里

你可能感兴趣的:(android进阶)