Jetpack 是 Android 开发中一组强大的库和工具,旨在帮助开发者更高效地构建高质量的应用程序。以下是 Jetpack 的主要组件及其功能的整理:
基础组件
1.1 ViewModel
作用:用于管理与 UI 相关的数据,并在配置更改(如屏幕旋转)时保持数据持久化。
使用方式:
- 创建 ViewModel 类,继承
ViewModel。 - 在 Activity 或 Fragment 中通过
ViewModelProvider获取 ViewModel 实例。 - 将数据存储在 ViewModel 中,并在 UI 中观察数据。
class MyViewModel: ViewModel() {
val data = MutableLiveData<String>()
fun loadData() {
data.value = "Hello, Jetpack!"
}
}
class MyActivity: AppCompatActivity() {
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
viewModel.data.observe(this, Observer { value ->
// 更新 UI
textView.text = value
})
viewModel.loadData()
}
}底层原理 & QA
1. ViewModelProvider(this)中的this是什么?
this指的是当前的Activity或Fragment实例。在ViewModelProvider(this)中,this是 ViewModelStoreOwner 的一个实例。Activity 和 Fragment 都实现了 ViewModelStoreOwner 接口,因此它们可以作为 ViewModelProvider 的参数。
2. ViewModelProvider 是什么?
ViewModelProvider 是一个用于创建和管理 ViewModel 实例的工具类。它确保在配置更改(如屏幕旋转)时,ViewModel 实例不会被销毁,并且可以在 Activity 或 Fragment 的生命周期内保持数据的一致性。
3. get 是从哪里获取 ViewModel 实例的?
get 方法是从 ViewModelStore 中获取 ViewModel 实例的。ViewModelStore 是一个用于存储 ViewModel 实例的容器,它与 Activity 或 Fragment 的生命周期相关联。当调用 ViewModelProvider(this).get(MyViewModel::class.java) 时,ViewModelProvider 会首先检查 ViewModelStore 中是否已经存在对应的 ViewModel 实例。如果存在,则直接返回该实例;如果不存在,则创建一个新的实例并将其存储在 ViewModelStore 中。
4. ViewModelProvider 是全局 Application 共用的空间吗?
不是的。ViewModelProvider 并不是全局 Application 共用的空间。每个 Activity 或 Fragment 都有自己的 ViewModelStore,用于存储与该 Activity 或 Fragment 相关的 ViewModel 实例。这意味着不同的 Activity 或 Fragment 之间的 ViewModel 实例是相互独立的。
5. ViewModelStore** 是什么?**
ViewModelStore 是一个简单的容器类,用于存储 ViewModel 实例。每个 Activity 或 Fragment 都有自己的 ViewModelStore,它会在 Activity 或 Fragment 的生命周期内管理 ViewModel 实例。
- 当
Activity或Fragment被销毁时(例如由于配置更改,如屏幕旋转),ViewModelStore会保留ViewModel实例。 - 当
Activity或Fragment被永久销毁时(例如用户按返回键退出),ViewModelStore会被清除,所有ViewModel实例也会被销毁。
6. ViewModelStore** 如何存储 ViewModel?**
ViewModelStore 内部使用一个 HashMap 来存储 ViewModel 实例。HashMap 的键是 ViewModel 的唯一标识符(通常是 ViewModel 的类名),值是对应的 ViewModel 实例。
public class ViewModelStore {
private final HashMap<String, ViewModel> mMap = new HashMap<>();
public void put(String key, ViewModel viewModel) {
mMap.put(key, viewModel);
}
public ViewModel get(String key) {
return mMap.get(key);
}
public void clear() {
mMap.clear();
}
}1.2 LiveData
作用:提供可观察的数据持有者,确保 UI 与数据保持同步。
使用方式:
- 在 ViewModel 中定义
LiveData或MutableLiveData。 - 在 Activity 或 Fragment 中观察
LiveData的变化。
val liveData = MutableLiveData<String>()
liveData.observe(this, Observer { value ->
// 当数据变化时更新 UI
textView.text = value
})
liveData.value = "New Value"1.3 Lifecycle管理
作用:Lifecycle 是 Jetpack 的核心组件之一,用于管理 Activity 和 Fragment 的生命周期。它可以帮助你在生命周期状态变化时执行相应的操作,避免内存泄漏和不必要的资源消耗。
使用方式:
- 实现
LifecycleObserver接口,监听生命周期事件。 - 在 Activity 或 Fragment 中注册观察者。
class MyObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onStart() {
Log.d("Lifecycle", "Activity started")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onStop() {
Log.d("Lifecycle", "Activity stopped")
}
}
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycle.addObserver(MyObserver())
}
}1.4 Room
作用:SQLite 数据库的抽象层,简化数据库操作。
使用方式:
- 定义实体类(Entity)。
- 创建 DAO 接口(Data Access Object)。
- 创建数据库类,继承
RoomDatabase。
@Entity
data class User(
@PrimaryKey val uid: Int,
@ColumnInfo val name: String?
)
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAll(): List<User>
@Insert
fun insert(user: User)
}
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
// 使用
val db = Room.databaseBuilder(
applicationContext,
AppDatabase::class.java, "database-name"
).build()
val user = User(1, "John")
db.userDao().insert(user)1.5 DataBinding
将 UI 组件与数据源直接绑定,减少模板代码。
架构组件
2.1 Navigation
作用:管理应用内的导航逻辑,简化 Fragment 和 Activity 之间的跳转。
使用方式:
- 在
res/navigation目录下创建导航图(XML 文件)。 - 使用
NavController控制导航。
<!-- res/navigation/nav_graph.xml -->
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/nav_graph"
app:startDestination="@id/fragmentA">
<fragment
android:id="@+id/fragmentA"
android:name="com.example.FragmentA" />
<fragment
android:id="@+id/fragmentB"
android:name="com.example.FragmentB" />
</navigation>val navController = findNavController(R.id.nav_host_fragment)
navController.navigate(R.id.fragmentB)2.2 WorkManager
作用:处理后台任务,即使应用关闭也能保证任务执行。
使用方式:
- 创建 Worker 类,继承
Worker。 - 使用
WorkManager调度任务。
class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
// 执行后台任务
return Result.success()
}
}
val workRequest = OneTimeWorkRequest.Builder(MyWorker::class.java).build()
WorkManager.getInstance(context).enqueue(workRequest)2.3 Paging
作用:分页加载数据,适用于列表或 RecyclerView。
使用方式:
- 创建
PagingSource或PagingDataAdapter。 - 在 RecyclerView 中使用
PagingDataAdapter。
class MyPagingSource: PagingSource<Int, User>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, User> {
// 加载分页数据
}
}
val pagingData = Pager(PagingConfig(pageSize = 20)) {
MyPagingSource()
}.flow
pagingData.collectLatest { pagingData ->
adapter.submitData(pagingData)
}2.4 Hilt
作用:基于 Dagger 的依赖注入框架,简化依赖管理。
使用方式:
- 在 Application 类上添加
@HiltAndroidApp注解。 - 使用
@Inject注入依赖。
@HiltAndroidApp
class MyApplication : Application()
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideMyDependency(): MyDependency {
return MyDependency()
}
}
class MyViewModel @Inject constructor(
private val myDependency: MyDependency
) : ViewModel() {
// 使用 myDependency
}关于依赖注入
依赖注入(Dependency Injection,DI)是一种设计模式,用于解耦代码和依赖关系。它的核心思想是:将对象的创建和依赖关系的管理交给外部容器,而不是在代码中硬编码。
在后端(如 Spring Boot)中的依赖注入
在 Spring Boot 中,依赖注入通常通过注解(如@Controller、@Service、@Component)来实现。Spring 容器会自动创建和管理这些 Bean,并将它们注入到需要的地方。
@Service
public class MyService {
public void doSomething() {
System.out.println("Doing something!");
}
}
@RestController
public class MyController {
@Autowired
private MyService myService;
@GetMapping("/do")
public void doSomething() {
myService.doSomething();
}
}在 Android 中的依赖注入
在 Android 中,依赖注入的作用和后端类似,但实现方式有所不同。Jetpack 提供了 Hilt 作为依赖注入框架,它基于 Google 的 Dagger 2,但更简单易用。
Hilt 的使用方式:
- 在 Application 类上添加
@HiltAndroidApp注解,启用 Hilt。 - 使用
@Module和@Provides定义依赖。 - 使用
@Inject注入依赖。
@HiltAndroidApp
class MyApplication : Application()
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideMyDependency(): MyDependency {
return MyDependency()
}
}
// 这里使用构造器注入,是推荐的注入方式
class MyViewModel @Inject constructor(
private val myDependency: MyDependency
) : ViewModel() {
fun doSomething() {
myDependency.doSomething()
}
}**@Module 和 @Provides **相当于 Spring Boot 中的 @Service 或 @Component,用于定义如何创建依赖。
在 Hilt 中,@Provides 注解用于标记一个方法,告诉 Hilt:“这个方法会返回一个依赖的实例”。这个方法通常定义在 @Module 注解的类或对象中。
为什么在方法上定义?
- 灵活性:方法可以包含复杂的逻辑来创建依赖实例。
- 解耦:将依赖的创建逻辑集中管理,而不是分散在代码中。
@HiltAndroidApp相当于 Spring Boot 中的 @SpringBootApplication,用于启用 Hilt 依赖注入框架。
@Inject相当于 Spring Boot 中的 @Autowired“@Resource,用于注入依赖。
和 SpringBoot 一样,Hilt 支持多种依赖注入方式,比如字段注入、构造器注入,方法注入(对应 SpringBoot 的 setter 注入)等等。构造函数注入不仅是 SpringBoot 的推荐方式,也是 Hilt 和 Dagger 中最常见的用法,也是官方推荐的方式。
**@InstallIn(SingletonComponent::class)**定义依赖的作用域和生命周期。SingletonComponent::class 表示依赖是单例的,整个应用生命周期内只会创建一个实例。相当于 SpringBoot 中的 @Scope(“singleton”)。
Hilt 的作用域比 Spring Boot 更细粒度,可以根据 Android 组件的生命周期来定义依赖的作用域。例如:
@InstallIn(SingletonComponent::class):应用级别的单例。@InstallIn(ActivityComponent::class):Activity 级别的单例。@InstallIn(FragmentComponent::class):Fragment 级别的单例。
行为组件
- CameraX简化相机功能的开发,兼容不同设备。
- DownloadManager管理文件下载任务。
- Media & Playback提供多媒体播放和控制功能。
- Permissions简化权限请求和管理。
UI 组件
4.1 Compose
作用:声明式 UI 工具包,用于构建现代 Android 界面。
使用方式:
- 使用
@Composable注解定义 UI 组件。 - 在 Activity 中使用
setContent设置 UI。
@Composable
fun Greeting(name: String) {
Text(text = "Hello, $name!")
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Greeting("Jetpack")
}
}
}- Fragment管理 UI 片段,支持模块化设计。
- RecyclerView高效显示大量数据列表。
- ViewPager2支持滑动的视图容器。
其他工具
**5.1 App Startup **优化应用启动时的初始化流程
作用:App Startup 用于优化应用启动时的初始化流程。它允许你将多个库的初始化任务集中管理,避免启动时的性能瓶颈。
使用方式:
- 创建
Initializer类,实现Initializer<T>接口。 - 在
AndroidManifest.xml中注册Initializer。
class MyInitializer : Initializer<MyDependency> {
override fun create(context: Context): MyDependency {
// 初始化逻辑
return MyDependency()
}
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList() // 依赖的其他 Initializer
}
}<!-- AndroidManifest.xml -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false">
<meta-data
android:name="com.example.MyInitializer"
android:value="androidx.startup" />
</provider>- Benchmark提供性能测试工具,帮助优化应用性能。
- Security提供加密和安全存储功能。
更新: 2026-01-15 14:43:29
原文: https://www.yuque.com/dongpozhouzi-mshe3/zhm85g/gs3dq0g0iqqgt7ss