Android LiveData使用

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

  • 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能夠在子線程處理。android

  • 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對象。app

  • 擴展LiveData

一般LiveData只關心觀察者的STARTED或RESUMED狀態,下面代碼片斷擴展了LiveDataide

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)
    }
}

實現包括如下重要方法:post

  • 當 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 對象,這意味着:gradle

  • 若是 Lifecycle 對象未處於活躍狀態,那麼即便值發生更改,也不會調用觀察者。
  • 銷燬 Lifecycle 對象後,會自動移除觀察者

固然能夠在多個 Activity、Fragment 和 Service 之間共享它們,只須要把 StockLiveData類實現爲單例。this

  • 轉換 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 對象。code

相關文章
相關標籤/搜索