簡體   English   中英

來自Transformation的數據綁定LiveData - Android Kotlin

[英]Data binding LiveData from Transformation - Android Kotlin

我正在學習kotlin和android架構組件。 我在谷歌地圖上有一個簡單的地圖切換按鈕用例。

我想使用數據綁定將地圖切換按鈕標簽綁定到我的ViewModel中的MutableLiveData字段。

我在Activity中的onCreate方法中設置MapViewModel中的mapType val。 如果我理解正確,這應該觸發mapLabel val由於使用Transformations.map而改變。

它不起作用......為什么?

這是我的版本:

  • Android studio 3.2 Canary 4
  • kotlin_version ='1.2.21'
  • support =“27.1.0”
  • arch_core =“1.1.0”
  • 數據綁定=“3.2.0-alpha04”

MapViewModel.kt

class MapViewModel : ViewModel() {

    val mapType: MutableLiveData<MapType> = MutableLiveData()

    val mapLabel: LiveData<String> = Transformations.map(mapType, {
        if (it == MapType.MAP) "SAT" else "MAP"
    })
}

enum class MapType {
    SAT, MAP
}

activity_maps.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="vm"
            type="uk.co.oliverdelange.wcr_android_kt.ui.map.MapViewModel" />
    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MapsActivity">

            <Button
                android:id="@+id/map_toggle"
                style="@style/Wcr_MapToggle"
                android:layout_marginTop="110dp"
                android:layout_marginEnd="12dp"
                android:layout_marginBottom="7dp"
                android:layout_gravity="top|end" 
                android:text="@{vm.mapLabel}" />
        </fragment>    
    </FrameLayout>
</layout>

MapsActivity.kt

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap
    private lateinit var viewModel: MapViewModel
    private lateinit var binding: ActivityMapsBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_maps)
        viewModel = ViewModelProviders.of(this).get(MapViewModel::class.java)
        binding.vm = viewModel

        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)

        // I can do it this way, but I don't want to. 
        // viewModel.mapLabel.observe(this, Observer { map_toggle.text = it })

        // Here is where i'm setting the MapType on the ViewModel.
        viewModel.mapType.value = MapType.MAP
    }

    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
    }
}

我已經使用MutableLiveData對象測試了綁定,我在活動中設置了字符串,它運行正常。 問題似乎與Transformations.map - 我剛剛理解錯了嗎?

此外,在調試時,我看到我的ViewModel中的mapType val沒有觀察者(不確定這是對還是錯,只是有趣)

這里的問題是,盡管綁定到mapLabel字段,但是當mapLabel字段的值發生更改時,視圖綁定未被更新。

原因是我沒有在綁定上設置生命周期所有者。

binding.setLifecycleOwner(this)

我第10次閱讀這篇博文后意識到自己的錯誤。

我的新MapsActivity.kt

class MapsActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mMap: GoogleMap
    private lateinit var viewModel: MapViewModel
    private lateinit var binding: ActivityMapsBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_maps)
        binding.setLifecycleOwner(this) //<- NEW!
        viewModel = ViewModelProviders.of(this).get(MapViewModel::class.java)
        binding.vm = viewModel

        val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
        mapFragment.getMapAsync(this)

        // Here is where i'm setting the MapType on the ViewModel.
        viewModel.mapType.value = MapType.MAP
    }

    override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap
    }
}

從好的方面來說,我學到了很多關於LiveData內部如何工作的知識!

它不起作用......為什么?

當您更改的值mapType ,價值mapLabel不會立即更改。 您需要再次設置mapLabel值。 例如,在為mapType設置值mapType ,調用method來更新mapLabel

// Here is where i'm setting the MapType on the ViewModel.
viewModel.mapType.value = MapType.MAP
viewModel.updateMapLabel()

你的viewModel:

fun updateMapLabel() {
    mapLabel.value =
        if (it == MapType.MAP) "SAT" else "MAP"
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM