前言
学习Kotlin
有一段时间了,想写一个项目总结收获,就有了这个可能是东半球最简洁的玩安卓客户端,在此感谢玩Android 的开放API。
简介
适合初学者入门的项目,通过对Kotlin的系统运用,实现的一个功能完备符合主流市场标准App。
虽然本项目的定位是入门级,但是该有的知识点却一点不少,对理解其他项目设计思想和封装技巧也很有帮助。
学习本项目你将有如下收获:
- Kotlin实战(函数进阶,泛型,反射,协程...)
- MVVM开发架构(ViewBinding,ViewModel,LiveData,RoomDatabase...)
- 单Activity多Fragment项目设计
- 暗夜模式
- 屏幕录制
- 字节码插桩
截图展示
项目目录结构
├── app app
| └── src
| └── main
| | └── java 源码目录
| | ├── activity Activity目录
| | | └── MainActivity 项目唯一Activity
| | ├── adapter Adapter目录
| | ├── fragment Fragment目录
| | ├── model ViewModel目录
| | └── App Application
| |
| └── build.gradle 模块构建配置
| └── channel 渠道配置文件
| └── dictionary 自定义混淆字典
| └── proguard-rules.pro 代码混淆配置文件
|
├── library_base 基础library(存放通用的封装源码)
| └── src
| └── main
| | ├── assets 原生文件目录
| | └── java 源码目录
| | ├── bus 消息总线目录
| | ├── dialog Dialog目录
| | ├── http 网络请求目录
| | ├── provider ContentProvider目录
| | ├── utils 工具类目录
| | └── view 自定义view目录
| |
| └── build.gradle 模块构建配置
|
├── library_common 公共library(存放各个 module 公共的源码及资源)
| └── src
| └── main
| | └── java 源码目录
| | ├── bean 实体类目录
| | └── constant 常量配置目录
| |
| └── build.gradle 模块构建配置
|
├── module_faq 问答模块(目录同app,不再展开)
├── module_home 首页模块(目录同app,不再展开)
├── module_navigation 导航模块(目录同app,不再展开)
├── module_project 项目模块(目录同app,不再展开)
├── module_system 体系模块(目录同app,不再展开)
├── module_user 用户模块(目录同app,不再展开)
|
├── plugin_statistic 统计插件模块
| └── src
| └── main
| └── groovy 源码目录
| | ├── bp 埋点统计目录
| | └── mt 耗时统计目录
| |
| └── resources 配置目录
| └── statistic.properties 插件配置
|
├── repos 统计插件生成目录
|
├── build.gradle 项目构建配置
├── config.gradle gradle编译文件 gradle依赖配置
├── config.properties 项目配置
├── gradle.properties gradle配置
└── settings.gradle 项目依赖配置
ViewBinding
通过视图绑定功能,您可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。
与使用 findViewById 相比,视图绑定具有 Null 安全,类型安全等很显著的优点。
LiveData
LiveData 是一种可观察的数据存储器类,它具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。
LiveData 的优势:不会发生内存泄漏,不会因 Activity 停止而导致崩溃,不再需要手动处理生命周期,数据始终保持最新状态,适当的配置更改,共享资源。
ViewModel
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
协程
协程是一种并发设计模式,您可以使用它来简化异步执行的代码。
协程的特点包括:轻量,内存泄漏更少,内置取消支持,Jetpack 集成。
Fragment + LiveData + ViewModel + 协程
以项目中 MainFragment 为例:
class MainViewModel : ViewModel() {
val hotKeyResult = MutableLiveData<HotKeyListBean>()
// 获取热词接口
fun getHotKey() {
// 通过viewModelScope创建一个协程
viewModelScope.launch {
// 构建请求体,传入请求参数
val request = HttpRequest("hotkey/json")
// 以get方式发起网络请求
val response = get<HotKeyListBean>(request)
// 通过LiveData更新数据
hotKeyResult.postValue(response)
}
}
}
class MainFragment : Fragment() {
// 使用 'by viewModels()' Kotlin属性委托获取 MainViewModel
private val viewModel: MainViewModel by viewModels()
private val hotKeyAdapter = HotKeyAdapter()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 观察 hotKeyResult 的变化来更新UI
viewModel.hotKeyResult.observe(viewLifecycleOwner, { result ->
result.data?.apply {
if (result.errorCode == "0") {
hotKeyAdapter.setNewData(this)
}
}
})
// 调用获取热词接口
viewModel.getHotKey()
}
}
基于LiveData封装的消息总线LiveDataBus
LiveDataBus具有生命周期感知,调用者不需要调用反注册,并且没有内存泄漏风险。
1、发送事件
LiveDataBus.with<String>("key").postEvent("value")
2、接收事件
LiveDataBus.with<String>("key").observe(viewLifecycleOwner, { it ->
println(it)
})
3、接收粘滞事件
LiveDataBus.with<String>("key").observeSticky(viewLifecycleOwner, { it ->
println(it)
})
基于RoomDatabase封装的DBHelper
通过键值对的方式来存储数据,不用再去关心RoomDatabase的复杂操作。
1、存储数据
DBHelper.set(“key”, "value")
2、获取数据
DBHelper.get(“key”)
字节码插桩
相关知识已发布在简书上,可点击下面链接跳转查看
主要开源框架
Thanks
感谢所有优秀的开源项目 _
如果喜欢的话希望给个 Star 或 Fork _
谢谢~~