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)
详情可参阅Android官方文档:https://developer.android.com/guide/fragments/communicate
技术栈
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(依赖注入)
需要单独写文档