Jetpack -- ViewModel使用與分析

簡介

  • 使用Android AAC組件構建自己的應用之後,爲了不讓自己停留在僅僅是使用的層面,所以從頭開始總結一邊AAC組件的使用以及注意的要點
  • ViewModel旨在以注重生命週期的方式存儲和管理界面相關的數據, ViewModel 類讓數據可在發生屏幕旋轉等配置更改後繼續存在

作用:

  • 將View中的數據模塊進行單獨的管理,使得Activity和Fragment更加簡單,只需要專注於界面本身不需要管理界面複雜的數據
  • 使用ViewModel的意義在於,平時當一個界面create或者destory的時候,我們需要使用onSaveInstanceState()從onCreate()中的捆綁包回覆其數據,但是當數據較大且序列化、反序列化較困難的時候,當採用ViewModel時候,數據是不會丟失的
  • 同時針對某些業務中的異步回調,我們可以利用ViewModel處理數據回調來解決這個問題

ViewModel使用

class MyViewModel : ViewModel() {
    public var number : Int = 0
}

class MainActivity : AppCompatActivity() {
    private lateinit var myViewModel: MyViewModel
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        // 首次調用onCreate時創建一個ViewModel ,重新創建的活動也會接受第一次創建的MyViewModel的實例,從而保證數據的一致性
        myViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)


        button.setOnClickListener({
            myViewModel.number++
            textView.setText(myViewModel.number.toString())
        })


        button2.setOnClickListener({
            myViewModel.number += 2
            textView.setText(myViewModel.number.toString())
        })


        textView.setText(myViewModel.number.toString())
    }
}
  • 注意
    • 當Activity finish的時候,框架會調用ViewModel的onCleared()方法來清理資源

ViewModel生命週期

  • 在這裏插入圖片描述
  • ViewModel生命週期是貫穿整個activity生命週期,包括Activity因旋轉造成的重創建,直到Activity銷燬纔會結束

使用ViewModel在Fragment之間共享數據

  • 之前在項目中如果兩個fragment需要通信,就會在Activity中將兩者綁定在一起,並且fragment之間還需要互相持有對方的引用
  • 使用ViewModel之後兩個fragment可以通過ViewModel關聯起來實現數據在兩個fragment之間的共享
 class SharedViewModel : ViewModel() {
        val selected = MutableLiveData<Item>()
        fun select(item: Item) {
            selected.value = item
        }
    }

    class MasterFragment : Fragment() {
        private lateinit var itemSelector: Selector
        private lateinit var model: SharedViewModel
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            model = activity?.run {
                ViewModelProviders.of(this)[SharedViewModel::class.java]
            } ?: throw Exception("Invalid Activity")
            itemSelector.setOnClickListener { item ->
                // Update the UI
            }
        }
    }


    class DetailFragment : Fragment() {
        private lateinit var model: SharedViewModel
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            model = activity?.run {
                ViewModelProviders.of(this)[SharedViewModel::class.java]
            } ?: throw Exception("Invalid Activity")
            model.selected.observe(this, Observer<Item> { item ->
                // Update the UI
            })
        }
    }
    

如何保證數據不會丟失

首先我們創建ViewModel
ViewModelProviders.of(this).get(MyViewModel::class.java)
of和get方法


public static ViewModelProvider of(@NonNull FragmentActivity activity,
        @Nullable Factory factory) {
    if (factory == null) {
        factory = activity.getDefaultViewModelProviderFactory();
    }
    return new ViewModelProvider(activity.getViewModelStore(), factory);
}


public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {

    // 通過key從viewModelStore中取出viewModel
    ViewModel viewModel = mViewModelStore.get(key);
    
    // 橫屏或者重建判斷取出的viewmodel和傳入的viewmodel的類型是否一致
    if (modelClass.isInstance(viewModel)) {
        if (mFactory instanceof OnRequeryFactory) {
            // 重新查詢該ViewModel
            ((OnRequeryFactory) mFactory).onRequery(viewModel);
        }
        return (T) viewModel;
    } else {
        //noinspection StatementWithEmptyBody
        if (viewModel != null) {
            // TODO: log a warning.
        }
    }
    if (mFactory instanceof KeyedFactory) {
        viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
    } else {
        viewModel = (mFactory).create(modelClass);
    }
        // 初始進入將ViewModel保存在viewmodelstore中
    mViewModelStore.put(key, viewModel);
    return (T) viewModel;
}
  • 注意:
    • 從上面的代碼可以分析出,Activity的銷燬重建都是從ViewModelStore中獲取的ViewModel----獲得的是同一個ViewModel,所以它可以保證數據不會丟失
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章