Jetpack(三) 之 Room 與 ViewModel

源碼分析: Jetpack 之 ViewModel 原理

ViewModel

  1. 管理數(shù)據(jù),把VIEW中的數(shù)據(jù)獨(dú)出來,單獨(dú)進(jìn)行管理
  2. 管理數(shù)據(jù)的保存與恢復(fù),比如屏幕轉(zhuǎn)動(dòng)问芬,用戶點(diǎn)回退按鈕收擦,或切換語言等操作
  3. 可以很方便的監(jiān)聽到UI上的數(shù)據(jù)變化
  4. 主要和LiveData與Room組合使用
    注意:ViewModel只是用來管理UI的數(shù)據(jù)的,千萬不要讓它持有View、Activity或者Fragment的引用(小心內(nèi)存泄露)掘托。

ViewModel數(shù)據(jù)恢復(fù)原理

public class NameViewModel extends ViewModel {
    public int i = 0;
    private MutableLiveData<String> currentName;
    public MutableLiveData<String> 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

參數(shù)1:getViewModelStore()方法中
從Activity的NonConfigurationInstances中取ViewModelStore,取不到就new一個(gè)

參數(shù)2:Factory中反射生成ViewModel實(shí)例

3 保存和恢復(fù)狀態(tài)>>

ComponentActivity
onRetainNonConfigurationInstance()保存狀態(tài) 轉(zhuǎn)屏?xí)r自動(dòng)調(diào)用
getLastNonConfigurationInstance()恢復(fù)狀態(tài)

4 保存viewModelStore>>

Activity在橫豎屏切換時(shí)悄悄保存了viewModelStore,放到了NonConfigurationInstances實(shí)例里面,橫豎屏切換時(shí)保存了又恢復(fù)了回來,相當(dāng)于ViewModel實(shí)例就一直在,也就避免了橫豎屏切換時(shí)的數(shù)據(jù)丟失.

ROOM使用

表定義 >>

@Entity

1. @PrimaryKey

主鍵

autoGenerate=true 自增長

2. @ColumnInfo

字段

name="zcwfeng" 字段名

3. @Ignore

表示一個(gè)屬性不加入生成表的字段卦睹,只是臨時(shí)使用

數(shù)據(jù)訪問對(duì)象的定義

@Dao ------ 定義Dao層

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

查詢

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

可以把參數(shù)加入查詢語句

//查詢一條記錄
    @Query("select * from Student where name like:name")
    Student findByName(String name);
    //查找部份ID號(hào)的記錄
    @Query("select * from Student where uid in (:userIds)")
    List<Student> getAllId(int[] userIds);
2. @Insert

插入

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

刪除

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

更新

@Update
    void update(Student student);

數(shù)據(jù)庫的定義 >>

@Database

定義數(shù)據(jù)庫中包含的表----entities={Student.class}
數(shù)據(jù)庫版本號(hào)------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<NameTuple> loadFullName();
}

表與表之間的實(shí)體聯(lián)系 >>

@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;
}

創(chuàng)建嵌套對(duì)象 >>

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;
}

傳遞參數(shù)集合 >>

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

可觀察的查詢 >>

@Dao
public interface MyDao {
    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
    public LiveData<List<User>> loadUsersFromRegionsSync(List<String> 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<List<UserPet>> 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<User> loadUserById(int id);
}

返回Cursor >>

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

Room數(shù)據(jù)庫遷移

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 原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末畦戒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子结序,更是在濱河造成了極大的恐慌兢交,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笼痹,死亡現(xiàn)場離奇詭異配喳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)凳干,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門晴裹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人救赐,你說我怎么就攤上這事涧团。” “怎么了经磅?”我有些...
    開封第一講書人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵泌绣,是天一觀的道長。 經(jīng)常有香客問我预厌,道長阿迈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任轧叽,我火速辦了婚禮苗沧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘炭晒。我一直安慰自己待逞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開白布网严。 她就那樣靜靜地躺著识樱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪震束。 梳的紋絲不亂的頭發(fā)上怜庸,一...
    開封第一講書人閱讀 52,821評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音驴一,去河邊找鬼休雌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛肝断,可吹牛的內(nèi)容都是我干的杈曲。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼胸懈,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼担扑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起趣钱,我...
    開封第一講書人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤涌献,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后首有,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體燕垃,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡枢劝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卜壕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您旁。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖轴捎,靈堂內(nèi)的尸體忽然破棺而出鹤盒,到底是詐尸還是另有隱情,我是刑警寧澤侦副,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布侦锯,位于F島的核電站,受9級(jí)特大地震影響秦驯,放射性物質(zhì)發(fā)生泄漏尺碰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一汇竭、第九天 我趴在偏房一處隱蔽的房頂上張望葱蝗。 院中可真熱鬧,春花似錦细燎、人聲如沸两曼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悼凑。三九已至,卻和暖如春璧瞬,著一層夾襖步出監(jiān)牢的瞬間户辫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來泰國打工嗤锉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渔欢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓瘟忱,卻偏偏與公主長得像奥额,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子访诱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容