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指的是当前的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 与数据保持同步。

使用方式:

  1. 在 ViewModel 中定义 LiveData 或 MutableLiveData。
  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. 创建 PagingSource 或 PagingDataAdapter。
  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


相关笔记