ViewModel官方介紹:
ViewModel類旨在以生命周期意識的方式存儲和管理與UI相關的資料。
ViewModel類允許資料在配置更改(例如螢幕旋轉)後繼續存在。
不做過多贅述。需要了解ViewModel的自行百度。這裡隻說使用。
首先,添加依賴:
//androidx的版本,包含ViewModel和LiveData
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
//非androidx版本
implementation "android.arch.lifecycle:extensions:1.1.1"
再然後就是建立 MyViewModel,繼承自 ViewModel:
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
public class MyViewModel extends androidx.lifecycle.ViewModel {
MutableLiveData<String> mString;
MutableLiveData<String> msgString;
public MutableLiveData<String> getString() {
if (mString == null) {
mString = new MutableLiveData<>();
}
return mString;
}
public MutableLiveData<String> getMsgString() {
if (msgString == null) {
msgString = new MutableLiveData<>();
}
return msgString;
}
public void startTask(){
new Thread(){
@Override
public void run() {
//請求網絡資料、資料庫、加載大圖等。
//如果在Activity轉屏的時候取消這些任務,那恢複的時候就要重新加載,勢必浪費資源
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//此處用的是LiveData,如果我們不用LiveData可能是通過EventBus之類的把資料傳遞出去的
msgString.postValue("我是來自3秒後的資料");
super.run();
}
}.start();
}
@Override
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
//做一些資料清理工作
Log.e("MViewModel","onCleared");
}
}
到此,VM類結束。下面是在activity中用法
在說之前先補充一下擷取ViewModel執行個體的方法:
//在Activity中
mViewModel = ViewModelProviders.of(this).get(MViewModel.class);
//在Fragment中,傳this是擷取和此Fragment綁定的ViewModel,
//傳getActivity則擷取到的是跟activity中的是同一個ViewModel
mViewModel = ViewModelProviders.of(this).get(MViewModel.class);
mViewModel = ViewModelProviders.of(getActivity).get(MViewModel.class);
下面是在activity中的具體用法:
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.Observer
import com.example.mytestbinder.R
import androidx.lifecycle.ViewModelProviders
import kotlinx.android.synthetic.main.activity_test.*
class TestActivity : AppCompatActivity() {
var myViewModel: MyViewModel? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
//初始化ViewModel
myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
tvLLL.setOnClickListener {
myViewModel?.startTask()
}
//訂閱資料變化
//對應VM中getmString方法訂閱
myViewModel?.getmString()?.observe(this,
Observer<String> { t ->
tv_test.text = t
})
//對應getMsgString方法訂閱
myViewModel?.getMsgString()?.observe(this,
Observer<String> { t ->
messagetv.text = t
})
supportFragmentManager.beginTransaction()
.replace(
R.id.testLL,
TestModelFragment(),
TestModelFragment::class.java.name
).commit()
}
}
為了說明ViewModel的作用域,我們再建一個TestFragment
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import com.example.mytestbinder.R;
public class TestModelFragment extends Fragment {
private Button btModel;
private MyViewModel mMyViewModel;
private TextView tvModel;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.model_fragment, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
btModel = view.findViewById(R.id.btModel);
tvModel = view.findViewById(R.id.tvModel);
//初始化擷取activity中的ViewModel
mMyViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
//對應VM中getMsgString方法訂閱
mMyViewModel.getMsgString().observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
tvModel.setText(s);
}
});
btModel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//發送消息,getMsgString()為消息發到具體對應的訂閱方法
mMyViewModel.getMsgString().setValue("Fragment 發送資料");
}
});
}
}
通過上面的代碼你會發現ViewModel使用起來非常的簡單,隻需要繼承ViewModel即可,其餘的生命周期之類的就完全不用我們考慮,它自己就能處理。除此之外同一Activity内的Fragment還能不通過Activity直接進行資料互動和共享,實作了真正意義上的解耦。