class MainActivity : AppCompatActivity() {
 // 获取无参构造的ViewModel实例
 val mViewModel = ViewModelProvider(this).get(MainViewModel::class.java)
 }


复制代码

资料:
官方文档: developer.android.com/topic/libra… Android ViewModel,再学不会你砍我: juejin.im/post/684490…

LiveData

LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 ActivityFragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者
LiveData 分为可变值的MutableLiveData和不可变值的LiveData常用方法:

fun test() {
 val liveData = MutableLiveData()
 // 设置更新数据源
 liveData.value = “LiveData”
 // 将任务发布到主线程以设置给定值
 liveData.postValue(“LiveData”)
 // 获取值
 val value = liveData.value
 // 观察数据源更改(第一个参数应是owner:LifecycleOwner 比如实现了LifecycleOwner接口的Activity)
 liveData.observe(this, {
 // 数据源更改后触发的逻辑
 })
 }


复制代码

资料:
官方文档: developer.android.com/topic/libra…

Lifecycle

Lifecycle 是一个类,用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。
LifecycleOwner 是单一方法接口,表示类具有 Lifecycle。它具有一种方法(即 getLifecycle()),该方法必须由类实现。
实现 LifecycleObserver 的组件可与实现 LifecycleOwner 的组件无缝协同工作,因为所有者可以提供生命周期,而观察者可以注册以观察生命周期。

资料:
官方文档: developer.android.com/topic/libra…

ViewBinding

通过视图绑定功能,您可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。
在大多数情况下,视图绑定会替代 findViewById使用方式:
按模块启用ViewBinding

// 模块下的build.gradle文件
 android {
 // 开启ViewBinding
 // 高版本AS
 buildFeatures {
 viewBinding = true
 }
 // 低版本AS 最低3.6
 viewBinding {
 enabled = true
 }
 }


复制代码

Activity 中 ViewBinding 的使用

// 之前设置视图的方法
 setContentView(R.layout.activity_main)// 使用ViewBinding后的方法
 val mBinding = ActivityMainBinding.inflate(layoutInflater)
 setContentView(mBinding.root)// ActivityMainBinding类是根据布局自动生成的 如果没有请先build一下项目
 // ViewBinding会将控件id转换为小驼峰命名法,所以为了保持一致规范,在xml里声明id时也请使用小驼峰命名法
 // 比如你有一个id为mText的控件,可以这样使用
 mBinding.mText.text = “ViewBinding”
 复制代码

Fragment 中 ViewBinding 的使用

// 原来的写法
 return inflater.inflate(R.layout.fragment_blank, container, false)// 使用ViewBinding的写法
 mBinding = FragmentBlankBinding.inflate(inflater)
 return mBinding.root


复制代码

资料:
官方文档: developer.android.com/topic/libra… CSDN: blog.csdn.net/u010976213/…

ARoute

ARoute是阿里巴巴的一个用于帮助 Android App 进行组件化改造的框架 —— 支持模块间的路由、通信、解耦
使用方式:

// 1.在需要进行路由跳转的Activity或Fragment上添加 @Route 注解
 @Route(path = “/test/activity”)
 public class YourActivity extend Activity {
 …
 }// 2.发起路由跳转
 ARouter.getInstance()
 .build(“目标路由地址”)
 .navigation()// 3.携带参数跳转
 ARouter.getInstance()
 .build(“目标路由地址”)
 .withLong(“key1”, 666L)
 .withString(“key3”, “888”)
 .withObject(“key4”, new Test(“Jack”, “Rose”))
 .navigation()// 4.接收参数
 @Route(path = RouteUrl.MainActivity2)
 class MainActivity : AppCompatActivity() {// 通过name来映射URL中的不同参数
 @Autowired(name = “key”)
 lateinit var name: Stringoverride fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(mBinding.root)
 // ARouter 依赖注入 ARouter会自动对字段进行赋值,无需主动获取
 ARouter.getInstance().inject(this)
 }
 }// 5.获取Fragment
 Fragment fragment = (Fragment) ARouter.getInstance().build(“/test/fragment”).navigation();


复制代码

资料:
官方文档:github.com/alibaba/ARo…

屏幕适配 AndroidAutoSize

屏幕适配使用的是 JessYan 大佬的 今日头条屏幕适配方案终极版
GitHub: github.com/JessYanCodi…使用方式:

// 在清单文件中声明


// 主单位使用dp 没设置副单位

// 默认是以竖屏的宽度为基准进行适配
// 如果是横屏项目要适配Pad(Pad适配尽量使用两套布局 因为手机和Pad屏幕宽比差距很大 无法完美适配)


// 以高度为基准进行适配 (还需要手动代码设置以高度为基准进行适配) 目前以高度适配比宽度为基准适配 效果要好

// 在Application 中设置
// 屏幕适配 AndroidAutoSize 以横屏高度为基准进行适配
AutoSizeConfig.getInstance().isBaseOnWidth = false
复制代码

EventBus APT

事件总线这里选择的还是EventBus,也有很多比较新的事件总线框架,还是选择了这个直接上手的 在框架内我对EventBus进行了基类封装,自动注册和解除注册,在需要注册的类上添加@EventBusRegister注解即可,无需关心内存泄漏及没及时解除注册的情况,基类里已经做了处理

@EventBusRegister
 class MainActivity : AppCompatActivity() {
 }


复制代码

很多使用EventBus的其实都没有发现APT的功能,这是EventBus3.0的重大更新,使用EventBus APT可以编译期生成订阅类,这样就可以避免使用低效率的反射,很多人不知道这个更新,用着3.0的版本,实际上却是2.0的效率 项目中已经在各模块中开启了EventBus APT,EventBus会在编译器对各模块生成订阅类,需要我们手动代码去集成这些订阅类

// 因为App包依赖了所有的模块所以选择在App包下的Application中进行设置
 // 开启EventBus APT
 EventBus
 .builder()
 .addIndex(“各模块生成的订阅类的实例 类名在 moduleBase.gradle 脚本中进行了设置 比如 Lib_Main 生成的订阅类就是 MainEventIndex”)
 .installDefaultEventBus()


复制代码

PermissionX

PermissionX 是郭霖的一个权限申请框架
使用方式:

PermissionX.init(this)
 .permissions(“需要申请的权限”)
 .request { allGranted, grantedList, deniedList -> }


复制代码