luckybilly / CC

业界首个支持渐进式组件化改造的Android组件化开源框架,支持跨进程调用。Componentize your android project gradually.
https://luckybilly.github.io/CC-website/
Apache License 2.0
4.04k stars 636 forks source link

用CC框架对登录进行AOP实现时,出现Call超时的问题 #56

Closed Foamtor closed 6 years ago

Foamtor commented 6 years ago

需求: 进入登录页面前,如果已经记住了密码,直接静默自动登录,否则进入到登录页面手动登录。 调用代码:

// 闪屏延迟400毫秒后进行登录
mDisposable = Observable.timer(400, TimeUnit.MILLISECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(aLong -> {
         //  这里会出现超时result就会一直为flase
          CCResult result = CC.obtainBuilder("component_login")
              .setActionName("init").setNoTimeout().build().call();
          if (result.isSuccess()) {
            toastMessage("登录成功");
            CC.obtainBuilder("component_navigation").build().call();
          } else {
            toastMessage("登录失败");
          }
        });

登录组件call()方法:


  @Override
  public boolean onCall(CC cc) {
    Context context = cc.getContext();
    String account = PreferenceManager.getDefaultSharedPreferences(context)
        .getString(Config.PREFERENCES_KEY_USER_ACCOUNT, "");
    String pwd = PreferenceManager.getDefaultSharedPreferences(context)
        .getString(Config.PREFERENCES_KEY_USER_PASSWORD, "");
    // 如果没有在Prenference中记录账号密码,直接进入登录页面
    if (TextUtils.isEmpty(account) || TextUtils.isEmpty(pwd)) {
      Intent intent = new Intent(context, LoginActivity.class);
      intent.putExtra("callId", cc.getCallId());
      if (!(context instanceof Activity)) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
      }
      context.startActivity(intent);
    } else {
    // 如果在Prenference中记录了账号密码,直接静默登录
      DataRepository dataRepository = new DataRepository(context);
      dataRepository.login(account, pwd, new DataSourceCallback<String>() {
        @Override
        public void onSuccess(String data) {
          CCResult result = CCResult.success();
          CC.sendCCResult(cc.getCallId(), result);
        }

        @Override
        public void onFailed(String msg) {
          CC.sendCCResult(cc.getCallId(), CCResult.error(msg));
        }
      });
    }
```java
**登录页`onDestroy()`方法:**
```java
  @Override
  public void onDestroy() {
    super.onDestroy();
    String callId = Objects.requireNonNull(getActivity()).getIntent().getStringExtra("callId");
    if (!TextUtils.isEmpty(callId)) {
      CCResult result;
      if (TextUtils.isEmpty(PreferenceManager.getDefaultSharedPreferences(getContext())
          .getString(Config.PREFERENCES_KEY_USER_PASSWORD, ""))) {
        result = CCResult.error("login_cancel");
      } else {
        result = CCResult.success();
      }
      CC.sendCCResult(callId, result);
    }
  }
```java
Foamtor commented 6 years ago

使用异步的callAsync()即可:

  private void start() {
    mDisposable = Observable.timer(400, TimeUnit.MILLISECONDS)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(aLong -> {
          CC.obtainBuilder("component_login")
              .setActionName("init").setNoTimeout().build().callAsync((cc, result) -> {
                if (result.isSuccess()) {
                  toastMessage("登录成功");
                  CC.obtainBuilder("component_navigation").build().call();
                } else {
                  toastMessage("登录失败");
                }
              });
        });
  }

有一点不是很理解,在CC框架实践(1):实现登录成功再进入目标界面功能中,

UserComponent的onCall( )方法里, 强制获取用户信息,若未登录则打开登录界面,在登录完成后再回调结果,异步实现

在OrderComponent中直接使用的call()为什么不会出现超时?

luckybilly commented 6 years ago

为了防止ANR,在主线程同步调用( cc.call() )时setNoTimeout()是无效的 可以放在子线程执行.observeOn(Schedulers.io())