Jetpack(三) 之 Room 与 ViewModel

源码分析: Jetpack 之 ViewModel 原理

ViewModel

  1. 管理数据,把VIEW中的数据独出来,单独进行管理
  2. 管理数据的保存与恢复,比如屏幕转动,用户点回退按钮,或切换语言等操作
  3. 可以很方便的监听到UI上的数据变化
  4. 主要和LiveData与Room组合使用
    注意:ViewModel只是用来管理UI的数据的,千万不要让它持有View、Activity或者Fragment的引用(小心内存泄露)。

ViewModel数据恢复原理

public class NameViewModel extends ViewModel {
    public int i = 0;
    private MutableLiveData currentName;
    public MutableLiveData getCurrentName(){
        if(currentName==null){
            currentName=new MutableLiveData<>();
        }
        return currentName;
    }
}

分析入口

1.获取viewModel>>
//获取viewModel
nameViewModel = ViewModelProviders.of(getActivity()).get(NameViewModel.class);

新版本

nameViewModel = new ViewModelProvider.NewInstanceFactory().create(NameViewModel.class);

或者

ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(NameViewModel.class);

2 ViewModelProviders.of() >>

保存了ViewModelStore和Factory并返回ViewModelProvider

参数1:getViewModelStore()方法中
从Activity的NonConfigurationInstances中取ViewModelStore,取不到就new一个

参数2:Factory中反射生成ViewModel实例

3 保存和恢复状态>>

ComponentActivity
onRetainNonConfigurationInstance()保存状态 转屏时自动调用
getLastNonConfigurationInstance()恢复状态

4 保存viewModelStore>>

Activity在横竖屏切换时悄悄保存了viewModelStore,放到了NonConfigurationInstances实例里面,横竖屏切换时保存了又恢复了回来,相当于ViewModel实例就一直在,也就避免了横竖屏切换时的数据丢失.

ROOM使用

表定义 >>

@Entity

1. @PrimaryKey

主键

autoGenerate=true 自增长

2. @ColumnInfo

字段

name="zcwfeng" 字段名

3. @Ignore

表示一个属性不加入生成表的字段,只是临时使用

数据访问对象的定义

@Dao ------ 定义Dao层

@Dao
public interface StudentDao {
.....
}
1. @Query

查询

@Query("select * from Student")
    List getAll();

可以把参数加入查询语句

//查询一条记录
    @Query("select * from Student where name like:name")
    Student findByName(String name);
    //查找部份ID号的记录
    @Query("select * from Student where uid in (:userIds)")
    List getAllId(int[] userIds);
2. @Insert

插入

@Insert
    void insert(Student... students);
3. @Delete

删除

 @Delete
    void delete(Student student);
4. @Update

更新

@Update
    void update(Student student);

数据库的定义 >>

@Database

定义数据库中包含的表----entities={Student.class}
数据库版本号------version=1

@Database(entities = {Student.class},version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract StudentDao userDao();
}

返回例的子集 >>

public class NameTuple {
    @ColumnInfo(name="first_name")
    public String firstName;

    @ColumnInfo(name="last_name")
    public String lastName;
}

@Dao
public interface MyDao {
    @Query("SELECT first_name, last_name FROM user")
    public List loadFullName();
}

表与表之间的实体联系 >>

@Entity(foreignKeys = @ForeignKey(entity = User.class,
                                  parentColumns = "id",
                                  childColumns = "user_id"))
public class Book {
    @PrimaryKey
    public int bookId;

    public String title;

    @ColumnInfo(name = "user_id")
    public int userId;
}

创建嵌套对象 >>

public class Address {
    public String street;
    public String state;
    public String city;

    @ColumnInfo(name = "post_code")
    public int postCode;
}

@Entity
public class User {
    @PrimaryKey
    public int id;

    public String firstName;

    @Embedded
    public Address address;
}

传递参数集合 >>

@Dao
public interface MyDao {
    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
    public List loadUsersFromRegions(List regions);
}

可观察的查询 >>

@Dao
public interface MyDao {
    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
    public LiveData> loadUsersFromRegionsSync(List regions);
}
@Dao
public interface MyDao {
   @Query("SELECT user.name AS userName, pet.name AS petName "
          + "FROM user, pet "
          + "WHERE user.id = pet.user_id")
   public LiveData> loadUserAndPetNames();


   // You can also define this class in a separate file, as long as you add the
   // "public" access modifier.
   static class UserPet {
       public String userName;
       public String petName;
   }
}

支持Rxjava >>

@Dao
public interface MyDao {
    @Query("SELECT * from user where id = :id LIMIT 1")
    public Flowable loadUserById(int id);
}

返回Cursor >>

@Dao
public interface MyDao {
    @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
    public Cursor loadRawUsersOlderThan(int minAge);
}

Room数据库迁移

Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
        .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
                + "`name` TEXT, PRIMARY KEY(`id`))");
    }
};

static final Migration MIGRATION_2_3 = new Migration(2, 3) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE Book "
                + " ADD COLUMN pub_year INTEGER");
    }
};

Jetpack(一)Lifecycle和LiveData
JetPacks之Lifecycles原理
JetPack之 LifeCycle LiveData

Jetpack(二)之DataBinding

Jetpack(三) 之 Room 与 ViewModel
Jetpack 之 ViewModel 原理

Jetpack (四) 之 Navigation
Jetpack Navigation 原理浅析

JetPack (五)之 Paging 分页库

Jetpack(六) 之 WorkManager
Jetpack WorkManager 原理

你可能感兴趣的:(Jetpack(三) 之 Room 与 ViewModel)