我希望能够在AndroidStudio中的其他项目模块中获得用户位置的2个不同的反应实现。
所以具体来说,可以使用gms,或者只使用原生的android LocationManager。
这是我的存储库界面:
interface RxLocationRepository {
@SuppressLint("MissingPermission")
fun onLocationUpdate(): Observable<Location>
fun stopLocationUpdates()
}
所以现在,我在这里实现这个接口,在AndroidStudio中的同一项目模块中的类中:
class RxLocationRepositoryImpl(val reactiveLocationProvider: ReactiveLocationProvider,
val reactiveLocationRequest: LocationRequest,
val isUsingLocationNativeApi: Boolean,
val locationManager: LocationManager,
val geoEventsDistanceMeters: Int,
val geoEventsIntervalSeconds: Int
) : RxLocationRepository {
var locationToPopulate: Location = Location(LocationManager.GPS_PROVIDER)
lateinit var mLocationCallbackNativeApi: LocationListener
private val subject: BehaviorSubject<Location> = BehaviorSubject.createDefault(locationToPopulate)
var locationEmitter: Observable<Location> = subject.hide()
init {
configureEmitter()
}
@SuppressLint("MissingPermission")
private fun configureEmitter(){
if (!isUsingLocationNativeApi)
locationEmitter = reactiveLocationProvider.getUpdatedLocation(reactiveLocationRequest)
else{
configureNativeLocationEmitter()
}
}
@SuppressLint("MissingPermission")
private fun configureNativeLocationEmitter() {
mLocationCallbackNativeApi = object : LocationListener {
override fun onLocationChanged(location: Location) {
subject.onNext(location)
}
override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {}
override fun onProviderEnabled(provider: String) {}
override fun onProviderDisabled(provider: String) {}
}
try {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
(geoEventsIntervalSeconds * 1000).toLong(),
geoEventsDistanceMeters.toFloat(),
mLocationCallbackNativeApi,
Looper.getMainLooper())
} catch (ignored: IllegalArgumentException) {
ignored.printStackTrace()
}
try {
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
(geoEventsIntervalSeconds * 1000).toLong(),
geoEventsDistanceMeters.toFloat(),
mLocationCallbackNativeApi,
Looper.getMainLooper())
} catch (ignored: IllegalArgumentException) {
ignored.printStackTrace()
}
}
@SuppressLint("MissingPermission")
override fun onLocationUpdate(): Observable<Location> {
return locationEmitter
}
override fun stopLocationUpdates() {
if(isUsingLocationNativeApi)
locationManager.removeUpdates(mLocationCallbackNativeApi)
}
}
所以一切都很好,但是现在我想在不同的项目模块中实现这个gms(所以我不需要在gradle中有gms依赖)以及在其他模块中的本机实现Android Studio。
AndroidStudio中项目的最终结构将类似于location_core,location_gms,location_native。
location_core一定不能知道location_gms和native,我想与他们相反 - 他们将依赖于location_core。
所以现在,我只有location_core项目模块和一个LocationClient类,它将提供上下文:
class LocationClient @Inject constructor(val nexoLocationManager: NexoLocationManager){
companion object {
private var locationClient: LocationClient? = null
fun obtainLocationClient(context: Context): LocationClient{
val result = locationClient ?:
DaggerLocationComponent
.builder()
.context(context)
.build()
.locationClient()
locationClient = result
return result
}
}
}
它正在使用一些Dagger组件,它为他提供了不同对象的所有实现。 所以我想移动这个LocationClient或者在location_core项目模块中将其抽象化,并在AndroidStudio中的每个location_gms和location_native项目模块中移动它的实现。
因此,每个中的LocationClient类将提供此RxRepository的不同实现。 现在,在每个location_gms和location_native项目模块中,我只有实现类,它以自己的方式实现了存储库rxLocationRepository(我从上面的实现中移出)。
问题是我不知道如何用Dagger管理所有这些。 现在我在我的location_core中使用这样的Dagger,这里是LocationComponent:
@Singleton
@Component(modules = arrayOf(LocationModule::class))
interface LocationComponent{
fun locationClient(): LocationClient
@Component.Builder
interface Builder {
@BindsInstance
fun context(context: Context): Builder
fun build(): LocationComponent
}
}
及其模块:
@Module
class LocationModule {
//some stuff
@Provides
@Singleton
fun providesRxLocationRepository(
reactiveLocationProvider: ReactiveLocationProvider,
reactiveLocationRequest: LocationRequest,
@Named("CONFIG_LOCATION_USE_NATIVE_API")isUsingLocationNativeApi: Boolean,
locationManager: LocationManager,
@Named("CONFIG_LOCATION_GEO_EVENTS_DISTANCE_METERS")geoEventsDistanceMeters: Int,
@Named("CONFIG_LOCATION_GEO_EVENTS_INTERVAL_SECONDS")geoEventsIntervalSeconds: Int
): RxLocationRepository = RxLocationRepositoryImpl(
reactiveLocationProvider,
reactiveLocationRequest,
isUsingLocationNativeApi,
locationManager,
geoEventsDistanceMeters,
geoEventsIntervalSeconds)
//some other stuff
}
那么如何在每个模块中编写实际的LocationClient - location_gms和location_native?如何使用Dagger提供每个location_gms和location_native项目模块中的rxLocationRepository的实现,这样我就可以在我的location_core模块中使用接口RxLocationRepository并且不用担心它的实现,因为它会在每个项目模块中?
当然,我必须指出,这3个模块永远不会在一起,我想,我猜每个build_variant中将有2个模块。 所以我必须摆脱location_core项目模块build.gradle中的google服务依赖。
更新
我怎么能在我的location_core中没有Dagger组件,我在其中测试如下:
val component = DaggerLocationTestInstrumentalComponent.builder().context(InstrumentationRegistry.getContext()).build()
val database = component.testDatabase()
val locationManager = component.locationClient().nexoLocationManager
答案 0 :(得分:1)
当然,我必须指出,这3个模块永远不会在一起,我想,我猜每个build_variant将是2个模块。
这是要注意的要点。您的组件定义不应位于location_core
内。相反,它应该在&#34;消费者&#34;侧。消费者,我指的是实际使用位置的模块。我们称之为consumer_module
。
我将如何处理这项任务。
location_gms
和location_native
都应包含LocationModule
,其实现方式不同。在两个模块中对LocationModule
使用相同的包名称。
consumer_module
包含LocationComponent
。根据构建变体,它将从LocationModule
或location_gms
解析为location_native
。
LocationModule
的另一种方法是相同的,但在consumer_module
两个LocationComponent
中创建。每个都有不同的构建变体。在这种方法中,您不必为LocationModule
保留相同的包名称。