1.什么是Jetpack?
- Jetpack是谷歌官方推出的一套Android开发组件集合,它就像是一个"开发工具百宝箱",帮助开发者更轻松地构建高质量的应用。想象一下,你要盖房子,Jetpack就是为你准备好的各种预制件和工具,让你不用从零开始造轮子。
2.为什么需要Jetpack?
- 减少样板代码:以前写Android应用要写很多重复的代码,Jetpack帮我们省去了这些麻烦
- 兼容性更好:自动处理不同Android版本的兼容问题
- 架构更清晰:提供标准化的开发模式,让代码更有条理
- 提高开发效率:很多常用功能已经封装好了,直接调用就行
3.Jetpack组件如何协同工作
一个典型的Jetpack架构是这样的:
UI层 (Activity/Fragment)
↑ 观察 ↓ 通知
ViewModel (持有LiveData)
↑ 调用 ↓ 返回
Repository (数据仓库)
↑ 获取 ↓ 提供
本地数据源(Room) 或 远程数据源(Retrofit)
4.Jetpack核心组件详解
4.1. Lifecycle(生命周期管理)
通俗理解:就像给你的代码装了个"生命监测仪",能感知Activity/Fragment的生命周期变化。
常用场景:
- 当页面显示时开始播放视频,页面隐藏时暂停
- 在合适的生命周期初始化或释放资源
java
java写法
1. 添加依赖(build.gradle)
dependencies {
implementation "androidx.lifecycle:lifecycle-common-java8:2.6.0" // Java 兼容库
}
2. 实现 LifecycleObserver(监听生命周期)
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import android.util.Log;
public class LocationObserver implements DefaultLifecycleObserver {
private static final String TAG = "LifecycleDemo";
@Override
public void onStart(LifecycleOwner owner) {
startLocationTracking();
Log.d(TAG, "onStart: 定位启动");
}
@Override
public void onStop(LifecycleOwner owner) {
stopLocationTracking();
Log.d(TAG, "onStop: 定位停止");
}
private void startLocationTracking() {
// 实际定位逻辑(如请求位置更新)
}
private void stopLocationTracking() {
// 释放定位资源
}
}
说明:
继承 DefaultLifecycleObserver,重写 onStart/onStop 等方法。
替代 @OnLifecycleEvent 注解(官方推荐方案)
3. 在 AppCompatActivity 中注册观察者
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册 LifecycleObserver
getLifecycle().addObserver(new LocationObserver());
}
}
关键点:
AppCompatActivity 已默认实现 LifecycleOwner 接口,直接通过 getLifecycle() 获取 Lifecycle 对象。
观察者自动绑定生命周期,无需手动调用生命周期方法。
4.2. ViewModel(数据管理)
通俗理解:相当于数据的"保险箱",屏幕旋转时数据不会丢失,而且不同Fragment可以共享同一个ViewModel。
特点:
- 独立于UI的生命周期
- 配置更改(如旋转屏幕)时数据不会丢失
- 便于UI组件间共享数据
4.3. LiveData(数据观察)
通俗理解:像是一个"数据广播站",当数据变化时会自动通知所有订阅者。
优点:
- 自动感知生命周期,避免内存泄漏
- 数据变化时自动更新UI
- 不需要手动处理订阅和取消订阅
以下是使用 Java 编写的 ViewModel + LiveData 完整范例,结合生命周期感知、数据持久化和屏幕旋转恢复等功能,适配最新 Jetpack 组件库
java
1. 添加依赖(build.gradle)
dependencies {
implementation "androidx.lifecycle:lifecycle-viewmodel:2.6.0"
implementation "androidx.lifecycle:lifecycle-livedata:2.6.0"
}
2. 创建 ViewModel 类(管理计数器逻辑)
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class CounterViewModel extends ViewModel {
// MutableLiveData 存储可变数据,对外暴露不可变的 LiveData
private final MutableLiveData<Integer> counter = new MutableLiveData<>(0);
public LiveData<Integer> getCounter() {
return counter;
}
// 增加计数
public void increment() {
counter.setValue(counter.getValue() + 1);
}
// 重置计数
public void reset() {
counter.setValue(0);
}
// ViewModel 销毁时释放资源
@Override
protected void onCleared() {
super.onCleared();
// 可在此取消网络请求或清理资源
}
}
关键点:
MutableLiveData 封装数据,对外暴露 LiveData 防止外部篡改
onCleared() 在 ViewModel 永久销毁时自动调用,避免内存泄漏
3. Activity 中初始化 ViewModel 并观察数据(MainActivity.java)
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModelProvider;
public class MainActivity extends AppCompatActivity {
private CounterViewModel viewModel;
private TextView tvCount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化 ViewModel(系统自动管理生命周期)
viewModel = new ViewModelProvider(this).get(CounterViewModel.class);
tvCount = findViewById(R.id.tv_count);
Button btnIncrement = findViewById(R.id.btn_increment);
Button btnReset = findViewById(R.id.btn_reset);
// 观察 LiveData 数据变化
LiveData<Integer> counterLiveData = viewModel.getCounter();
counterLiveData.observe(this, count -> {
tvCount.setText(String.valueOf(count)); // 数据更新时刷新 UI
});
// 按钮点击事件
btnIncrement.setOnClickListener(v -> viewModel.increment());
btnReset.setOnClickListener(v -> viewModel.reset());
}
}
关键点:
ViewModelProvider(this) 确保屏幕旋转时复用同一 ViewModel 实例
observe(this, ...) 自动绑定生命周期:仅在界面活跃时更新 UI,销毁时自动解绑
4. 布局文件(activity_main.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tv_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textSize="48sp"
android:layout_gravity="center"/>
<Button
android:id="@+id/btn_increment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="+1"
android:layout_marginTop="24dp"/>
<Button
android:id="@+id/btn_reset"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Reset"
android:layout_marginTop="16dp"/>
</LinearLayout>
4.4 Room(数据库)
通俗理解:SQLite数据库的"升级版",用起来更简单,像操作对象一样操作数据库。
核心三部分:
- Entity:定义数据表结构
- DAO (Data Access Object):数据库操作接口
- Database:数据库持有者
以下是使用 Java 编写的 Room 数据库完整示例,涵盖实体定义、DAO 接口、数据库构建及增删改查操作,适配最新 Jetpack 组件库(Room 2.6+)
java
1. 添加依赖(app/build.gradle)
dependencies {
implementation "androidx.room:room-runtime:2.6.1"
annotationProcessor "androidx.room:room-compiler:2.6.1" // Java 注解处理器
implementation "androidx.lifecycle:lifecycle-livedata:2.6.0" // LiveData 支持
}
2. 定义实体类(Entity)
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "users")
public class User {
@PrimaryKey(autoGenerate = true)
private int id;
private String name;
private int age;
// 必须有无参构造(或所有字段为 public)
public User() {}
// Getter 和 Setter
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}
@Entity:标记为数据库表,tableName 指定表名。
@PrimaryKey:主键,autoGenerate = true 表示自增
3. 定义 DAO 接口(数据访问对象)
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import androidx.lifecycle.LiveData;
import java.util.List;
@Dao
public interface UserDao {
@Insert
void insert(User user); // 插入单条数据
@Update
void update(User user); // 更新数据
@Delete
void delete(User user); // 删除数据
@Query("DELETE FROM users")
void deleteAll(); // 清空表
@Query("SELECT * FROM users")
LiveData<List<User>> getAllUsers(); // 返回 LiveData 实现实时更新[1,5](@ref)
@Query("SELECT * FROM users WHERE id = :userId")
User getUserById(int userId); // 条件查询
}
@Query:支持自定义 SQL 语句,编译时验证语法。
LiveData:返回可观察数据,UI 自动响应变化
4. 创建数据库类(Database)
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import android.content.Context;
@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
// 单例模式防止重复实例化
private static volatile AppDatabase INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
synchronized (AppDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.getApplicationContext(),
AppDatabase.class,
"app_database.db" // 数据库文件名
).build();
}
}
}
return INSTANCE;
}
}
@Database:声明数据库版本和实体类列表。
exportSchema = false:关闭 Schema 导出(生产环境建议开启备份
5. 在 Activity 中使用数据库
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import androidx.lifecycle.Observer;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private AppDatabase db;
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化数据库
db = AppDatabase.getInstance(this);
userDao = db.userDao();
// 插入数据(需在子线程执行)
new Thread(() -> {
User user = new User();
user.setName("Alice");
user.setAge(25);
userDao.insert(user);
}).start();
// 观察数据变化(自动在主线程回调)
userDao.getAllUsers().observe(this, users -> {
for (User u : users) {
System.out.println("User: " + u.getName() + ", Age: " + u.getAge());
}
});
}
}
线程管理:Room 禁止主线程操作数据库,需用 Thread/Executor 或异步框架(如 RxJava)。
LiveData 观察:数据变化时自动刷新 UI,避免手动查询