簡體   English   中英

如何使片段等待到 Android Kotlin 中的當前位置

[英]How to make a fragment wait to the current location in Android Kotlin

我想要一個片段等待用戶的當前位置,然后根據已傳遞給 viewModel 構造函數的坐標創建進入 init 塊內部的數據列表的 viewModel。

我試圖通過寫一個協程來解決這個問題,但是還沒有成功。 在檢索位置之前,正在實例化 viewModel。

OverviewFragment.kt

class OverviewFragment: Fragment() {


   private var searchOptions: SearchOptions? = null
   private var radiusCenterPointLocation: Location? = null
   private val job = Job()
   private val coroutineScope = CoroutineScope(Dispatchers.Main + job)

   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
       savedInstanceState: Bundle?): View? {

       val binding: FragmentOverviewBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_overview, container, false)

       binding.lifecycleOwner = this

       try {
           searchOptions = OverviewFragmentArgs.fromBundle(arguments!!).searchOptions
       } catch (e: Exception) {
       }

       if (radiusCenterPointLocation == null ) {
           coroutineScope.launch {
               radiusCenterPointLocation =
                   async{ getCurrentLocation()}.await()
           }
       }

       Log.i("onCreateView", "We got location")

       val viewModelFactory = OverviewViewModelFactory(searchOptions, radiusCenterPointLocation)

       val viewModel = ViewModelProviders.of(this,
           viewModelFactory).get(OverviewViewModel::class.java)

       binding.viewModel = viewModel

getCurrentLocation() function

suspend fun getCurrentLocation(): Location? {
        val fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context!!)
        return withContext(Dispatchers.Main) {
            val task = fusedLocationProviderClient.lastLocation
            while (!task.isSuccessful) {
                delay(1000)
            }
            Log.i("return location", "${task.result!!.latitude}")
            return@withContext task.result
        }
    }

這是日志顯示的有關位置的內容:

2019-10-18 11:31:49.095 11304-11304/com.package I/onCreateView: We got location
2019-10-18 11:31:51.291 11304-11304/com.package I/return location: 44.4255631

所以根據日志,創建viewModel需要后返回位置。 如何讓代碼“等待”getCurrentLocation() function 的結果?

UI 線程不應該等待任何東西。 我的意思是,如果 UI 進度條上還沒有可用的位置,應該顯示或類似的東西。

此外,MVVM 背后的想法(因此引入 ViewModels 的架構)是視圖對 state 做出反應,並且兩者都是獨立的。 因此,您的片段不應該要求位置,它應該只觀察包含該位置的實時數據。

所以,我建議如下:

Model:

class LocationModel {
    val locationData: MutableLiveData<Location> = MutableLiveData()

    init {
        getLocation()
    }

    fun getLocation() {
        ...
        locationData.set(position)
    }

    fun getLocationData(): LiveData<Location> { return locationData }
}

ViewModel:
// just "proxy" between Fragment, LocationModel and others Model

Fragment: 
class Fragment: Fragment() {
    fun onViewCreated() {
        viewModel.getLocationData().observe(viewLifecycleOwner) { location -> 
            if (location == null) {
                showProgress()
            } else {
                showLocation()
            }
        }
    }
}

我在這里知道協程和其他東西,因為您的主要問題是您想要阻止 UI 線程,直到可能的阻塞操作完成。 它將以 ANR 結束。

暫無
暫無

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

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