[英]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.