Android App Arch

Posted kelisi_king

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android App Arch相关的知识,希望对你有一定的参考价值。

android Arch

  1. 工程模块

    Module

  2. 界面导航

    UI Flow

    简要说明

    使用Jetpack Nav库采用单Activity架构模式

    • UI复用(Fragment)

    • Activity之间跳转动画的问题。界面跳转会出现状态栏闪现

    • Activity之间共享数据问题

      要使用单例(Application Scope)来保存数据

      而单Activity可通过共享的ViewModel来传递数据。

    • 向Fragment传递数据有时候会特别痛苦

    • Navigation UI库便于处理BotNavView,NavDrawer等

    启动页只处理权限申请相关,权限申请可选方案:

    https://codix.io/repo/27043/similar

    • Nammu

    • Dexter

    • RxPermissions

    • PermissionsDispatcher

    最终选用了RxPermission,放弃使用PermissionDispatcher,与Dagger有兼容问题(使用了@Deprecated method)

    DialogFragment作为全局的弹框界面单独拎了出来,优劣有待考证。

    技术细节

    • Fragment之间的数据传递
    • Fragment与Activity之间的数据传递
    • Activity之间的数据传递

    详情可参阅Android官方文档:https://developer.android.com/guide/fragments/communicate

  3. 数据流

    DataFlow

    简要说明

    • 技术栈

      LiveData + RxJava + Hilt + Dagger + Retrofit + OkHttp

    • 非特定情况下限定使用以上三种Layout,参阅图片中说明1.2.3条

      Layout 渲染效率对比结果

    • 控件实现方案与要点参阅以下

      https://material.io/components?platform=android

    • 建议只需使用ViewBinding

      PreferenceActivity 还不支持databinding

      • ViewBinding 是 DataBinding的子集(ViewBinding能做的事DataBinding都能做,反过来不行)

      • ViewBinding更高效,编译速度更快(Main Advantage)编译包体积更小

      • 使用了DataBinding没必要再使用viewbinding

      • ViewBinding不需要在布局文件嵌套一层TAG<layout>

    • Theme

      设计人员可使用以下工具参阅:

      https://material.io/resources/color/#!/?view.left=0&view.right=0

      应用主题相关

      是一个自定义Resource的集合(theme attribute),可被layout、style等引用。theme的attribute不限定于一个控件的属性,这些值实在整个应用中贯穿使用,

      是应用视图的一个抽象集合,便于更换整个应用的主题,类似于一个interface,然后在不同主题下实现不同的属性配置。

    • Style

      对同一类别控件封装管理

      view attribute的集合:key只能为控件定义好的属性名称,好处是可对同一类别控件的属性封装后可复用,便于统一管理,只对当前控件有效

    技术要点

    • 第三方lib callback回调如何转RxJava Observable

      使用ObservableEmitter

       public Observable<LoginResponse> handleLogin(String phone, String password) {
              logger.d(TAG, "do Phone " + phone + " Pwd Login");
              if (!sdkConfigured) {
                  //should never happen
                  throw new UnsupportedOperationException("CTChat SDK Not Configured Yet");
              }
              return Observable.create(emitter -> {
                  AccountManager.login(application, phone, password, new ObservableLoginCallback(emitter));
              });
         
         private final class ObservableLoginCallback implements LoginCallback {
              @NonNull
              private final ObservableEmitter<LoginResponse> emitter;
      
              public ObservableLoginCallback(@NonNull ObservableEmitter<LoginResponse> emitter) {
                  this.emitter = emitter;
              }
      
              @Override
              public void onLoginSuccess(boolean needChangePassword) {
                  logger.d(TAG, "on login success -> needChangePwd:" + needChangePassword);
                  emitter.onNext(new LoginResponse(SUCCESS, ""));
                  emitter.onComplete();
              }
      
              @Override
              public void onLoginError(int errCode) {
                  logger.w(TAG, "on login err -> code:" + errCode);
                  LoginResponse loginResponse = new LoginResponse(getLoginResponseCode(errCode), "");
                  emitter.onNext(loginResponse);
                  emitter.onComplete();
                         
                  }
              }
          }
      
    • 使用RxJava merge操作符进行本地数据与远端数据依次告知UI

    • 跟随Fragment声明周期的变量AutoClearedValue

      public class AutoClearedValue<T> {
          private T value;
      
          public AutoClearedValue(@NotNull Fragment fragment, T value) {
              this.value = value;
              fragment.getLifecycle().addObserver(new DefaultLifecycleObserver() {
                  @Override
                  public void onCreate(@NonNull LifecycleOwner owner) {
                      fragment.getViewLifecycleOwnerLiveData().observe(fragment, viewLifecycleOwner -> {
                          viewLifecycleOwner.getLifecycle().addObserver(new DefaultLifecycleObserver() {
                              @Override
                              public void onDestroy(@NonNull LifecycleOwner owner) {
                                  AutoClearedValue.this.value = null;
                              }
                          });
                      });
                  }
              });
          }
      
          public T get() {
              return value;
          }
      }
      
    • DI(依赖注入)

      需要单独写文档

以上是关于Android App Arch的主要内容,如果未能解决你的问题,请参考以下文章

无法访问“com.ex.app.MainActivity”的超类型“android.arch.lifecycle.LifecycleOwner”

Android App Arch

Android 官方现代 App 架构解读 - 启程

Android App 在片段中创建 ListView 引用时关闭

如何从Android中的片段单击按钮打开片段

片段不能转换为 android.app.activity