Android LiveData使用


LiveData是一個可觀察的數據持有者類。 與常規observable不同,LiveData是生命周期感知的,當生命周期處於STARTED或RESUMED狀態,則LiveData會將其視為活動狀態,這意味着它尊重其他應用程序組件的生命周期,例如Activity,Fragment或Service。
LiveData具有以下優點:

  • UI和數據保持一致:遵循觀察者模式,生命周期狀態更改時,LiveData會通知Observer對象
  • 避免內存泄漏:觀察者綁定到Lifecycle對象,並在其相關生命周期被破壞后自行清理
  • 不會因stop而崩潰:處於非活動狀態,不會接收到LiveData事件,如Activity變為不可見
  • 自動感知生命周期:LiveData自動管理在觀察時意識到相關的生命周期狀態變化。
  • 數據始終保持最新:生命周期變為非活動狀態再次變為活動狀態時接收最新數據。 例如,Activity不可見變為可見時立即接收最新數據
  • 解決Configuration changes問題:當屏幕旋轉或者回收時,重新創建Activity或Fragment,可以即時收到數據變更
  • 共享資源:使用單例擴展LiveData,就可在app中共享它
  • gradle配置
def lifecycle_version = "2.0.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" 
  • 創建LiveData對象
class TestViewModel : ViewModel() {
    private lateinit var userName: MutableLiveData<String>

    fun getUserName(): MutableLiveData<String> {
        if (!::userName.isInitialized) {
            userName = MutableLiveData()
            loadUsers()
        }
        return userName
    }

    private fun loadUsers() {
        userName.value = "test"
    }
}
  • 觀察和變更LiveData對象
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var model = ViewModelProviders.of(this).get(TestViewModel::class.java)
        model.getUserName().observe(this, Observer {
            txt_test.text = it
        })// 觀察
        btn_test.setOnClickListener {
            model.getUserName().value = "test 2"
        }// 變更
    }
}

在變更數據的使用有兩種方式可用,一個是setValue,另外一個是postValue,區別是setValue只能在主線程處理,postValue可以在子線程處理。

  • LiveData結合Databinding使用
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        var model = ViewModelProviders.of(this).get(TestViewModel::class.java)
        binding.let {
            it.data = model
            it.setLifecycleOwner(this)
        }
        btn_test.setOnClickListener {
            model.getUserName().value = "test 2"
        }
    }
}

binding對象需要調用setLifecycleOwner(LifecycleOwner lifecycleOwner)設置lifecycleOwner對象。

  • 擴展LiveData

通常LiveData只關心觀察者的STARTED或RESUMED狀態,下面代碼片段擴展了LiveData

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    private var mStockManager: StockManager? = null

    private val mListener = object : SimplePriceListener() {
        fun onPriceChanged(price: BigDecimal) {
            value = price
        }
    }

    init {
        mStockManager = StockManager(symbol)
    }

    override fun onActive() {
        mStockManager.requestPriceUpdates(mListener)
    }

    override fun onInactive() {
        mStockManager.removeUpdates(mListener)
    }
}

實現包括以下重要方法:

  • 當 LiveData 對象具有活躍觀察者時,會調用 onActive() 方法。這意味着,您需要從此方法開始觀察數據更新。
  • 當 LiveData 對象沒有任何活躍觀察者時,會調用 onInactive() 方法。由於沒有觀察者在監聽,因此沒有理由與 StockManager 服務保持連接。
  • setValue(T) 方法將更新 LiveData 實例的值,並將更改通知給任何活躍觀察者。
  • 使用擴展LiveData
class TestFragment : Fragment() {

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        val stockLiveData = StockLiveData("")
        stockLiveData.observe(this, Observer {
            // update UI
        })
    }
}

observe() 方法將傳遞 Fragment(它是 LifecycleOwner 的實例)作為第一個參數。這樣做表示此觀察者綁定到與所有者關聯的 Lifecycle 對象,這意味着:

  • 如果 Lifecycle 對象未處於活躍狀態,那么即使值發生更改,也不會調用觀察者。
  • 銷毀 Lifecycle 對象后,會自動移除觀察者

當然可以在多個 Activity、Fragment 和 Service 之間共享它們,只需要把 StockLiveData類實現為單例。

  • 轉換 LiveData

LiveData 對象分派給觀察者之前對存儲在其中的值進行更改,或者您可能需要根據另一個實例的值返回不同的 LiveData 實例。其提供了以下方法進行轉換

  • Transformations.map()
LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});
  • Transformations.switchMap()
LiveData<String> userId = ...;
LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );

要實現您自己的轉換,可以使用 MediatorLiveData 類,該類可以監聽其他 LiveData 對象並處理它們發出的事件,其可以正確地將其狀態傳播到源 LiveData 對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM