【问题标题】:proper place to use location api in android mvvm architecture在 android mvvm 架构中使用位置 api 的正确位置
【发布时间】:2019-08-11 09:48:30
【问题描述】:

我有一个场景,我想显示用户当前的天气数据,因为我正在获取他/她当前的纬度/经度并对其进行反向地理编码以获取城市名称。获得城市名称后,我将拨打网络电话并显示天气数据。除此之外,我还需要执行许多定位操作。

所以我创建了一个名为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)
  }
}

【问题讨论】:

  • 你有什么发现吗?我也有类似的问题。
  • 到目前为止,我在我的活动中使用它。但仍在寻找推荐的解决方案。

标签: android android-mvvm


【解决方案1】:

我也在解决同样的问题。我还必须处理使用 MVVM 架构向用户显示天气数据的问题。此刻,我被困在你现在所在的同一点上。解决方案似乎是一种称为“依赖注入(DI)”的东西。基本上,我们可以使用像“Dagger 2”这样的工具/框架将像Context 这样的依赖项注入到我们的ViewModel。 DI 比直接将Context 传递到ViewModel 具有更低的耦合性,并导致更好地符合 MVVM。因此,IMO FusedLocationProvider 的实际位置将在 ViewModel 中,但在实施 DI 之后。也许其他人可以更好地详细说明我的解释。一旦我自己实施依赖注入,我将更新我的答案。

【讨论】:

  • 听起来不错。我已将ApplicationContextLocationManager 一起使用,并将LocationUtils(持有不同方法以提供基于位置的功能的类)注入ViewModel。仍在寻找常见和最佳做法。
【解决方案2】:

我把它放在我的 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观察输出。

【讨论】:

    猜你喜欢
    • 2018-04-26
    • 2020-02-28
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    • 2016-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多