Skip to content

Commit

Permalink
Merge pull request #12 from Jintin/feature/state
Browse files Browse the repository at this point in the history
add state flow type support
  • Loading branch information
Jintin authored Dec 20, 2020
2 parents 2bcca16 + 4417ffb commit 081ba16
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 13 deletions.
6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 17 additions & 9 deletions app/src/main/java/com/jintin/fancylocation/app/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ class MainActivity : AppCompatActivity() {
companion object {
const val TYPE_LIVEDATA = 0
const val TYPE_FLOW = 1
const val TYPE_STATEFLOW = 2
}

private val mainViewModel by viewModels<MainViewModel>()
private val viewModel by viewModels<MainViewModel>()

private val type = TYPE_FLOW
private val type = TYPE_STATEFLOW

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -44,30 +45,37 @@ class MainActivity : AppCompatActivity() {
when (type) {
TYPE_LIVEDATA -> liveDataObserve()
TYPE_FLOW -> flowObserve()
TYPE_STATEFLOW -> stateFlowObserve()
}
}

@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
private fun flowObserve() {
lifecycleScope.launch {
@Suppress("EXPERIMENTAL_API_USAGE")
mainViewModel.locationFlow.get().collect {
updateUI(it)
}
viewModel.locationFlow.get().collect(::updateUI)
}
}

@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
private fun liveDataObserve() {
mainViewModel.locationLiveData.observe(this) {
updateUI(it)
private fun stateFlowObserve() {
lifecycleScope.launch {
viewModel.locationStateFlow.start()
viewModel.locationStateFlow.value.collect(::updateUI)
}
}

@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
private fun liveDataObserve() {
viewModel.locationLiveData.observe(this, ::updateUI)
}

private fun updateUI(locationData: LocationData) {
findViewById<TextView>(R.id.location).text = when (locationData) {
LocationData.Init -> "Init state"
LocationData.Loading -> "Start loading"
LocationData.Fail -> "Fail to get location"
is LocationData.Success -> locationData.location.toString()
is LocationData.Fail -> "Fail to get location"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package com.jintin.fancylocation.app
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import com.google.android.gms.location.LocationRequest
import com.jintin.fancylocation.ILocationProvider
import com.jintin.fancylocation.LocationProvider
import com.jintin.fancylocation.asFlow
import com.jintin.fancylocation.asLiveData
import com.jintin.fancylocation.*
import kotlinx.coroutines.ExperimentalCoroutinesApi

class MainViewModel(application: Application) : AndroidViewModel(application) {
Expand All @@ -19,6 +16,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {

// @ExperimentalCoroutinesApi
// val locationFlow = LocationFlow(application, locationRequest)
// val locationStateFlow = LocationFlow(application, locationRequest)
// val locationLiveData = LocationLiveData(application, locationRequest)

// we can also provide custom vendor by create your own LocationProvider
Expand All @@ -27,4 +25,5 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
@ExperimentalCoroutinesApi
val locationFlow = locationProvider.asFlow()
val locationLiveData = locationProvider.asLiveData()
val locationStateFlow = locationProvider.asStateFlow()
}
2 changes: 2 additions & 0 deletions lib/src/main/java/com/jintin/fancylocation/LocationData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package com.jintin.fancylocation
import android.location.Location

sealed class LocationData {
object Init : LocationData()
object Loading : LocationData()
data class Success(val location: Location) : LocationData()
object Fail : LocationData()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ fun ILocationProvider.asLiveData(): LocationLiveData {
@ExperimentalCoroutinesApi
fun ILocationProvider.asFlow(): LocationFlow {
return LocationFlow(this)
}

fun ILocationProvider.asStateFlow(): LocationStateFlow {
return LocationStateFlow(this)
}
1 change: 1 addition & 0 deletions lib/src/main/java/com/jintin/fancylocation/LocationFlow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class LocationFlow(

@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
fun get(): Flow<LocationData> = channelFlow {
channel.sendBlocking(LocationData.Loading)
locationProvider.requestLocationUpdates(object : ILocationObserver {
override fun onLocationResult(location: Location) {
channel.sendBlocking(LocationData.Success(location))
Expand Down
48 changes: 48 additions & 0 deletions lib/src/main/java/com/jintin/fancylocation/LocationStateFlow.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.jintin.fancylocation

import android.Manifest
import android.content.Context
import android.location.Location
import androidx.annotation.RequiresPermission
import com.google.android.gms.location.LocationRequest
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.coroutines.coroutineContext

class LocationStateFlow(
private val locationProvider: ILocationProvider
) {
private val _value = MutableStateFlow<LocationData>(LocationData.Init)
val value: StateFlow<LocationData> get() = _value

constructor(
context: Context,
locationRequest: LocationRequest
) : this(LocationProvider(context, locationRequest))

@RequiresPermission(anyOf = [Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION])
suspend fun start() {
_value.value = LocationData.Loading
locationProvider.requestLocationUpdates(object : ILocationObserver {
override fun onLocationResult(location: Location) {
_value.value = LocationData.Success(location)
}

override fun onLocationFailed() {
_value.value = LocationData.Fail
}
})
with(CoroutineScope(coroutineContext)) { // spawns and uses parent scope!
launch {
suspendCancellableCoroutine<Unit> {
it.invokeOnCancellation {
locationProvider.removeLocationUpdates()
}
}
}
}
}
}

0 comments on commit 081ba16

Please sign in to comment.