關於ViewModel 介紹,文章不過多闡述。官方文檔html
本文將從三個方面作必定闡述java
你須要處理配置變化android
orientation = portrait
,可是你沒法禁止用戶去改變語言、文字大小。這樣就可能會致使Activity被移除或者從新建立爲何onSaveInstanceState
依舊不夠git
傳統的作法都是在配置發生變化即 onSaveInstanceState
方法去save data, 在onCreate去restore datagithub
可是這裏有兩個限制api
onSaveInstanceState
方法不可以緩存較大的數據,筆者以前嘗試緩存上百兆數據發現拋出了TransactionTooLargeException
serializable
或者 Parceable
, 可是有時候這些數據來自第三方庫,咱們不能修改它,對於某些場景,很難在onSaveonSaveInstanceState
中保存數據基於上述兩點,ViewModel應運而生緩存
- 配置改變先後數據存儲與恢復
public class ZeroViewModel extends ViewModel {
public User user;
}
複製代碼
public class ZeroDemo extends AppCompatActivity {
private TextView tv;
private ZeroViewModel vm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tv_btn);
tv = findViewById(R.id.tv_simple);
vm = ViewModelProviders.of(this).get(ZeroViewModel.class);
System.out.println("szw vm.user = " + vm.user);
}
// android:onClick="onClickSimpleButton"
public void onClickSimpleButton(View v) {
vm.user = new User(23, "jorden");
}
}
複製代碼
旋轉屏幕,vm.user 依舊 != null網絡
public class SameClass01 extends AppCompatActivity {
private TextView tv;
private ZeroViewModel vm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tv_btn);
tv = findViewById(R.id.tv_simple);
vm = ViewModelProviders.of(this).get(ZeroViewModel.class);
System.out.println("szw SameClass01 : " + vm.user);
}
// launch the second instance
// android:onClick="onClickSimpleButton"
public void onClickSimpleButton(View v) {
vm.user = new User(100, "SuperMario");
startActivity(new Intent(this, SameClass01.class));
}
}
複製代碼
即便有兩個同類的Activity實例,第一個vm.user 持有的依舊是Mario,第二個vm.user 持有null . 這符合筆者的預期oracle
public class SameClass02 extends AppCompatActivity {
private TextView tv;
private ZeroViewModel vm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tv_btn);
tv = findViewById(R.id.tv_simple);
vm = ViewModelProviders.of(this).get(ZeroViewModel.class);
System.out.println("szw SameClass02 onCreate() : " + vm.user);
}
// android:onClick="onClickSimpleButton"
public void onClickSimpleButton(View v) {
vm.user = new User(22, "test");
}
// android:onClick="onClickSimpleButton2"
public void onClickSimpleButton2(View v) {
System.out.println("szw SameClass02 : saved = "+vm.user);
}
}
複製代碼
先啓動SameClass02 ,執行onClickSimpleButton,finish從新打開,日誌輸出nullapp
上述兩個例子表現正常
public class SameVm {
public static User user;
}
複製代碼
public class ZeroDemo extends AppCompatActivity {
private TextView tv;
private ZeroViewModel vm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tv_btn);
tv = findViewById(R.id.tv_simple);
String value = savedInstanceState == null ? "emptyBundle" : savedInstanceState.getString("key");
System.out.println("szw onCreate() " + value);
vm = ViewModelProviders.of(this).get(ZeroViewModel.class);
System.out.println("szw vm.user = " + vm.user);
System.out.println("szw static = "+SameVm.user);
}
// android:onClick="onClickSimpleButton"
public void onClickSimpleButton(View v) {
vm.user = new User(23, "jorden");
SameVm.user = new User(21, "king");
}
}
複製代碼
旋轉屏幕後,日誌輸出
szw vm.user = User{id=23, name='jorden'}
szw static = User{id=21, name='king’}
複製代碼
Terminate Application
和1一樣的操做
szw vm.user = null
szw static = null
複製代碼
從上面兩個例子,感受沒什麼不一樣。他們都能緩存數據,終止應用程序都會被銷燬
它們的不一樣之處:
- ViewModel 主要是爲了解耦,有點相似於MVP中的P,ViewModel 是MvvM中VM。你能在ViewModel中作異步操做(i.e訪問網絡),你能夠改變data而且讓View接受到通知LiveData
- static value 能被任何類修改,可是ViewModel 是Activity的私有變量,有點相似ThreadLocal
- ViewModel 能夠判斷Activity是正常銷燬或者配置改變,進而作出不一樣的響應,finish->removedata ,configurationchange->savedata,靜態變量卻不能
onSaveInstanceState
方法源碼以下
public class DupliViewModel extends ViewModel {
private SingleLiveEvent<String> message = new SingleLiveEvent<>();
public void fetchMessage(){
message.setValue("A New Value");
}
public LiveData<String> getMessage() {
return message;
}
}
複製代碼
public class DupliObserverDemo extends AppCompatActivity {
private TextView tv;
private DupliObserverDemo self;
private DupliViewModel vm;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tv_btn);
self = this;
tv = findViewById(R.id.tv_simple);
vm = ViewModelProviders.of(this).get(DupliViewModel.class);
vm.getMessage().observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
System.out.println("szw updated ~");
Toast.makeText(self, "updated "+s, Toast.LENGTH_SHORT).show();
}
});
}
// android:onClick="onClickSimpleButton"
public void onClickSimpleButton(View v) {
vm.fetchMessage();
}
}
複製代碼