Jetpack 是 Android 开发中一组强大的库和工具,旨在帮助开发者更高效地构建高质量的应用程序。以下是 Jetpack 的主要组件及其功能的整理:

基础组件

1.1 ViewModel

作用:用于管理与 UI 相关的数据,并在配置更改(如屏幕旋转)时保持数据持久化。

使用方式

  1. 创建 ViewModel 类,继承ViewModel
  2. 在 Activity 或 Fragment 中通过ViewModelProvider获取 ViewModel 实例。
  3. 将数据存储在 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指的是当前的ActivityFragment实例。在ViewModelProvider(this)中,thisViewModelStoreOwner 的一个实例。ActivityFragment 都实现了 ViewModelStoreOwner 接口,因此它们可以作为 ViewModelProvider 的参数。

2. ViewModelProvider 是什么?

ViewModelProvider 是一个用于创建和管理 ViewModel 实例的工具类。它确保在配置更改(如屏幕旋转)时,ViewModel 实例不会被销毁,并且可以在 ActivityFragment 的生命周期内保持数据的一致性。

3. get 是从哪里获取 ViewModel 实例的?

get 方法是从 ViewModelStore 中获取 ViewModel 实例的。ViewModelStore 是一个用于存储 ViewModel 实例的容器,它与 ActivityFragment 的生命周期相关联。当调用 ViewModelProvider(this).get(MyViewModel::class.java) 时,ViewModelProvider 会首先检查 ViewModelStore 中是否已经存在对应的 ViewModel 实例。如果存在,则直接返回该实例;如果不存在,则创建一个新的实例并将其存储在 ViewModelStore 中。

4. ViewModelProvider 是全局 Application 共用的空间吗?

不是的。ViewModelProvider 并不是全局 Application 共用的空间。每个 ActivityFragment 都有自己的 ViewModelStore,用于存储与该 ActivityFragment 相关的 ViewModel 实例。这意味着不同的 ActivityFragment 之间的 ViewModel 实例是相互独立的。

5. ViewModelStore** 是什么?**

ViewModelStore 是一个简单的容器类,用于存储 ViewModel 实例。每个 ActivityFragment 都有自己的 ViewModelStore,它会在 ActivityFragment 的生命周期内管理 ViewModel 实例。

  • ActivityFragment 被销毁时(例如由于配置更改,如屏幕旋转),ViewModelStore 会保留 ViewModel 实例。
  • ActivityFragment 被永久销毁时(例如用户按返回键退出),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 与数据保持同步。

使用方式

  1. 在 ViewModel 中定义 LiveDataMutableLiveData
  2. 在 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 的生命周期。它可以帮助你在生命周期状态变化时执行相应的操作,避免内存泄漏和不必要的资源消耗。

使用方式

  1. 实现 LifecycleObserver 接口,监听生命周期事件。
  2. 在 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 数据库的抽象层,简化数据库操作。

使用方式

  1. 定义实体类(Entity)。
  2. 创建 DAO 接口(Data Access Object)。
  3. 创建数据库类,继承 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 之间的跳转。

使用方式

  1. res/navigation 目录下创建导航图(XML 文件)。
  2. 使用 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

作用:处理后台任务,即使应用关闭也能保证任务执行。

使用方式

  1. 创建 Worker 类,继承 Worker
  2. 使用 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。

使用方式

  1. 创建 PagingSourcePagingDataAdapter
  2. 在 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 的依赖注入框架,简化依赖管理。

使用方式

  1. 在 Application 类上添加 @HiltAndroidApp 注解。
  2. 使用 @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 的使用方式

  1. 在 Application 类上添加 @HiltAndroidApp 注解,启用 Hilt。
  2. 使用 @Module@Provides 定义依赖。
  3. 使用 @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 界面。

使用方式

  1. 使用 @Composable 注解定义 UI 组件。
  2. 在 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 用于优化应用启动时的初始化流程。它允许你将多个库的初始化任务集中管理,避免启动时的性能瓶颈。

使用方式

  1. 创建 Initializer 类,实现 Initializer<T> 接口。
  2. 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


相关笔记