我有一个场景,我想向用户显示我正在获取他/她当前的lat/lng的当前天气数据,并对其进行反向地理编码以获得城市名称。一旦我有了城市名称,我将进行网络呼叫并显示天气数据。除此之外,我还需要执行许多定位操作。
所以我创建了一个名为LocationUtils.kt
的类。我正在遵循MVVM架构,我想知道哪个层是调用LocationUtils
方法的理想层,是view
层、viewmodel
层还是data
层。因为FusedLocationProvider
需要context
,如果我在ViewModel
中使用它,它会泄漏。那么如何解决这个问题呢?
LocationUtils.kt
class LocationUtils {
private lateinit var fusedLocationClient: FusedLocationProviderClient
private fun isLocationEnabled(weakContext: Context?): Boolean {
return when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> {
// This is new method provided in API 28
val locationManager = weakContext?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.isLocationEnabled
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT -> {
// This is Deprecated in API 28
val mode = Settings.Secure.getInt(
weakContext?.contentResolver, Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF
)
mode != Settings.Secure.LOCATION_MODE_OFF
}
else -> {
val locationProviders = Settings.Secure.getString(weakContext?.contentResolver, Settings.Secure.LOCATION_PROVIDERS_ALLOWED)
return !TextUtils.isEmpty(locationProviders)
}
}
}
@SuppressLint("MissingPermission")
fun getCurrentLocation(
weakContext: WeakReference<Context>,
success: (String?) -> Unit,
error: () -> Unit
) {
if (isLocationEnabled(weakContext.get())) {
weakContext.get()
?.let { context ->
fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
getCurrentCity(context, location, success)
}
}
} else {
error()
}
}
private fun getCurrentCity(
context: Context,
location: Location?,
success: (String?) -> Unit
) {
val city = try {
location?.let {
val geocoder = Geocoder(context, Locale.getDefault())
val address = geocoder.getFromLocation(it.latitude, it.longitude, 1)
address[0].locality
}
} catch (e: Exception) {
"Bangalore"
}
success(city)
}
}
发布于 2019-08-29 05:37:18
我也在解决同样的问题。我还必须处理使用MVVM架构向用户显示天气数据的问题。此时此刻,我被困在你现在所处的同一点。解决方案似乎是所谓的“依赖注入(DI)”。基本上,我们可以使用'Dagger 2‘这样的工具/框架将Context
等依赖项注入到我们的ViewModel
中。DI比直接将Context
传递给ViewModel
具有更低的耦合性,并导致更好的顺应性。所以,在实现DI之后,FusedLocationProvider
的实际位置将在ViewModel中。也许其他人可以更好地阐述我的解释。一旦我自己实现了依赖注入,我就会更新我的答案。
发布于 2020-02-20 17:51:04
我把它放到我的ViewModel里了。为了将context
作为参数传递给ViewModel
,您可以扩展AndroidViewModel
而不是ViewModel
。示例:
class CurrentViewModel(application: Application) : AndroidViewModel(application) {
val context = application
val locationResolver = LocationResolver(context)//this one converts latitude and longitude into City name of type String
fun detectCity() {
Log.d(LocationResolver.TAG, "entered detectLocation()")
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
fusedLocationClient.lastLocation
.addOnSuccessListener { location ->
if (location != null) {
Repository._currentName.value = locationResolver.getLocationFromCoordinates(
location.latitude,
location.longitude
)
Log.d(
LocationResolver.TAG,
"New city name is:" + Repository.currentLocationCity
)
}
}
}
然后,您可以通过DataBinding
观察输出。
https://stackoverflow.com/questions/57448952
复制相似问题