使用 Kotlin 中前台位置服务的数据更新 RecyclerView 时遇到问题

问题描述 投票:0回答:1

问题:我正在 Kotlin 中开发一个简单的测试应用程序,其前台位置服务每 5 秒更新一次 GPS 坐标(纬度和经度)。该应用程序有 1 个主要 Activity 和 3 个片段,通过基本导航连接。在第三个片段中,有一个 RecyclerView 应该接收并附加新的位置更新。我成功地通过硬编码按钮将项目添加到列表中,但我不知道如何将新位置更新自动从服务发布到片段。

代码片段:在我的 LocationService 中,我正在使用新位置更新通知,但很难将更新后的位置发送到片段。这是相关代码:

private var locationViewModel = SampleViewModel()
   override fun onCreate() {
        super.onCreate()
        locationClient = DefaultLocationClient(
            this,
            LocationServices.getFusedLocationProviderClient(applicationContext)
        )
        locationViewModel = ViewModelProvider(applicationContext)[SampleViewModel::class.java]
        //Type mismatch.
            Required:
              ViewModelStoreOwner
               Found:
              Context!

    }


// In LocationService
private fun updateLocationList(lat: String, lon: String) {
    val event = TripEvent(lat, lon)
    // Tried using ViewModel here, but can't access application context
    //locationViewModel.addTripEvent(event)
}

问题:如何有效地将位置更新从前台服务传递到片段,以便 RecyclerView 自动更新新数据?

我的尝试:我尝试使用共享 ViewModel (SampleViewModel) 来更新列表,但在尝试声明和访问服务中的 ViewModel 时遇到了问题。主要挑战是 ViewModelProvider 无法在服务中工作,因为它无法访问应用程序上下文。

android kotlin viewmodel foreground-service
1个回答
0
投票

1。将 LocalBroadcastManager 与 BroadcastReceiver 结合使用

//In LocationService
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import android.content.Intent

private fun updateLocationList(lat: String, lon: String) {
    val intent = Intent("LOCATION_UPDATE")
    intent.putExtra("latitude", lat)
    intent.putExtra("longitude", lon)
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
// In your fragment
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.localbroadcastmanager.content.LocalBroadcastManager

private val locationUpdateReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        val lat = intent?.getStringExtra("latitude")
        val lon = intent?.getStringExtra("longitude")
        lat?.let {
            lon?.let {
                // Update your RecyclerView adapter here
                val event = TripEvent(lat, lon)
                // Assuming you have a function in your adapter to add items
                myAdapter.addTripEvent(event)
            }
        }
    }
}

override fun onStart() {
    super.onStart()
    LocalBroadcastManager.getInstance(requireContext())
        .registerReceiver(locationUpdateReceiver, IntentFilter("LOCATION_UPDATE"))
}

override fun onStop() {
    super.onStop()
    LocalBroadcastManager.getInstance(requireContext())
        .unregisterReceiver(locationUpdateReceiver)
}



2。如果您更愿意坚持使用 ViewModel,您可以使用带有服务绑定的共享 ViewModel

// In LocationService
import android.os.Binder

class LocationService : Service() {
    private val binder = LocalBinder()
    
    inner class LocalBinder : Binder() {
        fun getService(): LocationService = this@LocationService
    }

    override fun onBind(intent: Intent?): IBinder {
        return binder
    }

    private fun updateLocationList(lat: String, lon: String) {
        val event = TripEvent(lat, lon)
        locationViewModel.addTripEvent(event)  // You can use the ViewModel now
    }
}
private lateinit var locationService: LocationService
private var bound = false

private val serviceConnection = object : ServiceConnection {
    override fun onServiceConnected(className: ComponentName, service: IBinder) {
        val binder = service as LocationService.LocalBinder
        locationService = binder.getService()
        bound = true
    }

    override fun onServiceDisconnected(arg0: ComponentName) {
        bound = false
    }
}

override fun onStart() {
    super.onStart()
    Intent(this, LocationService::class.java).also { intent ->
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
    }
}

override fun onStop() {
    super.onStop()
    unbindService(serviceConnection)
    bound = false
}

© www.soinside.com 2019 - 2024. All rights reserved.