iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
Mobile Development

Android Kotlin開發 -小嫩雞的30篇精選筆記系列 第 25

MVVM架構(二) [下] viewModel範例實作

說明

如下圖我們今天要做的頁面架構是,我們在一個Activity裡面放了三個fragment,分別是文章、活動與影片頁面。今天的需求是,在Activity層按下編輯鈕時,fragment必須要監聽到這件事並且浮出左側的radio button與下方的刪除鈕。今天我們要的方法是在activity建立一個viewModel,然後讓各個fragment去訂閱viewModel的資料變化來達到效果。或許除了用viewModel可能還有更快更好的方法,但今天就是當作一個viewModel的練習嘛,先不要太嚴格。

  • implelmentation

//目前最新版是2.2.0
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
  • BaseViewModelFactory

class BaseViewModelFactory<T>(private val creator: () -> T): ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return creator() as T
    }
}
  • 定義兩個全域函式

待會會利用這裡的方法來取得viewModel

inline fun <reified T : ViewModel> FragmentActivity.getViewModel(noinline creator: (() -> T)? = null): T {
    return if (creator == null)
        ViewModelProvider(this).get(T::class.java)
    else
        ViewModelProvider(this, BaseViewModelFactory(creator)).get(T::class.java)
}

inline fun <reified T : ViewModel> Fragment.getViewModel(noinline creator: (() -> T)? = null): T {
    return if (creator == null)
        ViewModelProvider(this).get(T::class.java)
    else
        ViewModelProvider(this, BaseViewModelFactory(creator)).get(T::class.java)
}
  • RemoveVM

宣告一個viewModel,裡面放一筆資料,屬於mutableLiveData,型態為boolean

class RemoveVM : ViewModel() {

    val isEditable by lazy {
        MutableLiveData<Boolean>()
    }
}
  • Activity

  1. 宣告一個全域的viewModel,等等fragment才叫得到它。
companion object{
         lateinit var removeVM :RemoveVM
    }
  1. onCreate
        //取得viewModel實體
        removeVM = getViewModel { RemoveVM() }
        //先把viewModel中的那筆資料設為false
        removeVM.isEditable.value = false
        
        //編輯鈕點擊監聽事件
        btn_edit_my_collection.setMyClickListener {

            if(removeVM.isEditable.value==false) {
                removeVM.isEditable.value = true
                btn_edit_my_collection.text = "取消"
            }
            else {
                removeVM.isEditable.value = false
                btn_edit_my_collection.text = "編輯"
            }
        }
  • Fragment

三個fragment都一樣。

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        rootView = inflater.inflate(R.layout.your_fragment, container, false)
        return rootView
    }
    
    
override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        
        //建立一個監聽器叫做statusObserver,監聽的資料型態是boolean
        val statusObserver = Observer<Boolean> {

            //若這筆資料變成true
            if (it) {
                //刪除鈕出現
                rootView.spacing_line.visibility = View.VISIBLE
                rootView.btn_remove.visibility = View.VISIBLE
                rootView.btn_remove.text = "刪除 ( 0 )"
                
                //我的recyclerview的每個項目也都有另外設一個屬性叫isEditable
                //藉由判斷true or false來決定要不要顯示左側的圓形radio button
                //這裡改成true,也就是通知adapter現在要顯示radio button了
                myData.myList.forEach { it.isEditable = true }
                adapter.notifyDataSetChanged()


            } 
            //若這筆資料變成false
            else {
                rootView.spacing_line.visibility = View.GONE
                rootView.btn_remove.visibility = View.GONE
                myCollectionData.articleList.forEach {
                    it.isEditable = false
                }
                adapter.notifyDataSetChanged()
            }
        }

        //剛剛我們設了監聽器,可以用來監聽一個型態為boolean值的資料的變化
        //那我們到底要監聽誰呢?
        //我們現在指定 我們要監聽removeVM中的isEditable這筆資料
        //owner是activity,也就是包著三個fragment的activity,
        //監聽器的生命就是跟著這個activity的生命週期走
        removeVM?.isEditable?.observe(activity!!, statusObserver)
}
  • 完成,吃烤肉。


上一篇
MVVM架構(二) [上]
下一篇
Android x Kotlin : 簡易實作第一堂-螢幕亮度調整
系列文
Android Kotlin開發 -小嫩雞的30篇精選筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言