Create MerchantViewModel and MerchantRepository, the first to hold the merchants data and deliver it to the MerchantsFragment and the second to serve as a single source to fetch the Merchants list. When it gets a request for the merchants it retrieves and serves the list from the database and meanwhile refreshes the list from the WebService.
This commit is contained in:
parent
6aad0ca624
commit
4bb53de009
5 changed files with 100 additions and 33 deletions
|
@ -1,8 +1,10 @@
|
||||||
package cy.agorise.bitsybitshareswallet.database.daos
|
package cy.agorise.bitsybitshareswallet.database.daos
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
|
@ -12,4 +14,7 @@ interface MerchantDao {
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insertAll(merchants: List<Merchant>)
|
fun insertAll(merchants: List<Merchant>)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM merchants")
|
||||||
|
fun getAll(): LiveData<List<Merchant>>
|
||||||
}
|
}
|
|
@ -12,17 +12,12 @@ import android.view.ViewGroup
|
||||||
import com.google.android.gms.maps.GoogleMap
|
import com.google.android.gms.maps.GoogleMap
|
||||||
import com.google.android.gms.maps.OnMapReadyCallback
|
import com.google.android.gms.maps.OnMapReadyCallback
|
||||||
import com.google.android.gms.maps.SupportMapFragment
|
import com.google.android.gms.maps.SupportMapFragment
|
||||||
import com.google.gson.GsonBuilder
|
|
||||||
|
|
||||||
import cy.agorise.bitsybitshareswallet.R
|
import cy.agorise.bitsybitshareswallet.R
|
||||||
import cy.agorise.bitsybitshareswallet.network.MerchantsWebservice
|
|
||||||
import cy.agorise.bitsybitshareswallet.network.FeathersResponse
|
|
||||||
import retrofit2.Call
|
|
||||||
import retrofit2.Response
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import com.google.android.gms.maps.CameraUpdateFactory
|
import com.google.android.gms.maps.CameraUpdateFactory
|
||||||
import com.google.android.gms.maps.model.*
|
import com.google.android.gms.maps.model.*
|
||||||
import com.google.maps.android.clustering.Cluster
|
import com.google.maps.android.clustering.Cluster
|
||||||
|
@ -31,10 +26,11 @@ import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
||||||
import cy.agorise.bitsybitshareswallet.utils.Constants
|
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||||
import cy.agorise.bitsybitshareswallet.utils.MerchantMarkerRenderer
|
import cy.agorise.bitsybitshareswallet.utils.MerchantMarkerRenderer
|
||||||
import cy.agorise.bitsybitshareswallet.utils.toast
|
import cy.agorise.bitsybitshareswallet.utils.toast
|
||||||
|
import cy.agorise.bitsybitshareswallet.viewmodels.MerchantViewModel
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
|
|
||||||
class MerchantsFragment : Fragment(), OnMapReadyCallback, retrofit2.Callback<FeathersResponse<Merchant>>,
|
class MerchantsFragment : Fragment(), OnMapReadyCallback,
|
||||||
ClusterManager.OnClusterClickListener<Merchant>,
|
ClusterManager.OnClusterClickListener<Merchant>,
|
||||||
ClusterManager.OnClusterItemClickListener<Merchant>,
|
ClusterManager.OnClusterItemClickListener<Merchant>,
|
||||||
ClusterManager.OnClusterItemInfoWindowClickListener<Merchant>{
|
ClusterManager.OnClusterItemInfoWindowClickListener<Merchant>{
|
||||||
|
@ -48,6 +44,8 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, retrofit2.Callback<Fea
|
||||||
|
|
||||||
private lateinit var mMap: GoogleMap
|
private lateinit var mMap: GoogleMap
|
||||||
|
|
||||||
|
private lateinit var mMerchantViewModel: MerchantViewModel
|
||||||
|
|
||||||
private var mClusterManager: ClusterManager<Merchant>? = null
|
private var mClusterManager: ClusterManager<Merchant>? = null
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@ -63,6 +61,8 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, retrofit2.Callback<Fea
|
||||||
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
|
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
|
||||||
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
|
val mapFragment = childFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
|
||||||
mapFragment.getMapAsync(this)
|
mapFragment.getMapAsync(this)
|
||||||
|
|
||||||
|
mMerchantViewModel = ViewModelProviders.of(this).get(MerchantViewModel::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun verifyLocationPermission() {
|
private fun verifyLocationPermission() {
|
||||||
|
@ -123,17 +123,11 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, retrofit2.Callback<Fea
|
||||||
mClusterManager?.setOnClusterItemClickListener(this)
|
mClusterManager?.setOnClusterItemClickListener(this)
|
||||||
mClusterManager?.setOnClusterItemInfoWindowClickListener(this)
|
mClusterManager?.setOnClusterItemInfoWindowClickListener(this)
|
||||||
|
|
||||||
val gson = GsonBuilder()
|
mMerchantViewModel.getAllMerchants().observe(this, Observer<List<Merchant>> {merchants ->
|
||||||
.setLenient()
|
mClusterManager?.clearItems()
|
||||||
.create()
|
mClusterManager?.addItems(merchants)
|
||||||
val retrofit = Retrofit.Builder()
|
mClusterManager?.cluster()
|
||||||
.baseUrl(Constants.MERCHANTS_WEBSERVICE_URL)
|
})
|
||||||
.addConverterFactory(GsonConverterFactory.create(gson))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val ambassadorService = retrofit.create<MerchantsWebservice>(MerchantsWebservice::class.java)
|
|
||||||
val call = ambassadorService.getMerchants(0)
|
|
||||||
call.enqueue(this)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyMapTheme() {
|
private fun applyMapTheme() {
|
||||||
|
@ -155,19 +149,6 @@ class MerchantsFragment : Fragment(), OnMapReadyCallback, retrofit2.Callback<Fea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call<FeathersResponse<Merchant>>, response: Response<FeathersResponse<Merchant>>) {
|
|
||||||
if (response.isSuccessful) {
|
|
||||||
val res: FeathersResponse<Merchant>? = response.body()
|
|
||||||
val merchants = res?.data ?: return
|
|
||||||
mClusterManager?.addItems(merchants)
|
|
||||||
mClusterManager?.cluster()
|
|
||||||
} else {
|
|
||||||
Log.e("error_bitsy", response.errorBody()?.string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(call: Call<FeathersResponse<Merchant>>, t: Throwable) { /* Do nothing */ }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Animates the camera update to focus on an area that shows all the items from the cluster that was tapped.
|
* Animates the camera update to focus on an area that shows all the items from the cluster that was tapped.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,7 +9,9 @@ import retrofit2.http.Query
|
||||||
interface MerchantsWebservice {
|
interface MerchantsWebservice {
|
||||||
|
|
||||||
@GET("/api/v1/merchants")
|
@GET("/api/v1/merchants")
|
||||||
fun getMerchants(@Query(value = "\$skip") skip: Int): Call<FeathersResponse<Merchant>>
|
fun getMerchants(@Query(value = "\$skip") skip: Int,
|
||||||
|
@Query(value = "\$limit") limit: Int = 50):
|
||||||
|
Call<FeathersResponse<Merchant>>
|
||||||
|
|
||||||
@GET("api/v2/tellers")
|
@GET("api/v2/tellers")
|
||||||
fun getTellers(@Query(value = "\$skip") skip: Int): Call<FeathersResponse<Teller>>
|
fun getTellers(@Query(value = "\$skip") skip: Int): Call<FeathersResponse<Teller>>
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
package cy.agorise.bitsybitshareswallet.repositories
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.AsyncTask
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import cy.agorise.bitsybitshareswallet.database.BitsyDatabase
|
||||||
|
import cy.agorise.bitsybitshareswallet.database.daos.MerchantDao
|
||||||
|
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
||||||
|
import cy.agorise.bitsybitshareswallet.network.FeathersResponse
|
||||||
|
import cy.agorise.bitsybitshareswallet.network.MerchantsWebservice
|
||||||
|
import cy.agorise.bitsybitshareswallet.utils.Constants
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Response
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class MerchantRepository internal constructor(context: Context) : retrofit2.Callback<FeathersResponse<Merchant>> {
|
||||||
|
|
||||||
|
private val mMerchantDao: MerchantDao
|
||||||
|
|
||||||
|
init {
|
||||||
|
val db = BitsyDatabase.getDatabase(context)
|
||||||
|
mMerchantDao = db!!.merchantDao()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a LiveData object directly from the database while the response from the WebService is obtained.
|
||||||
|
*/
|
||||||
|
fun getAll(): LiveData<List<Merchant>> {
|
||||||
|
refreshMerchants()
|
||||||
|
return mMerchantDao.getAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshMerchants() {
|
||||||
|
val retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl(Constants.MERCHANTS_WEBSERVICE_URL)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val ambassadorService = retrofit.create<MerchantsWebservice>(MerchantsWebservice::class.java)
|
||||||
|
val call = ambassadorService.getMerchants(0)
|
||||||
|
call.enqueue(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call<FeathersResponse<Merchant>>, response: Response<FeathersResponse<Merchant>>) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val res: FeathersResponse<Merchant>? = response.body()
|
||||||
|
val merchants = res?.data ?: return
|
||||||
|
insertAllAsyncTask(mMerchantDao).execute(merchants)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<FeathersResponse<Merchant>>, t: Throwable) { /* Do nothing */ }
|
||||||
|
|
||||||
|
private class insertAllAsyncTask internal constructor(private val mAsyncTaskDao: MerchantDao) :
|
||||||
|
AsyncTask<List<Merchant>, Void, Void>() {
|
||||||
|
|
||||||
|
override fun doInBackground(vararg merchants: List<Merchant>): Void? {
|
||||||
|
// TODO Delete all first
|
||||||
|
mAsyncTaskDao.insertAll(merchants[0])
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package cy.agorise.bitsybitshareswallet.viewmodels
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import cy.agorise.bitsybitshareswallet.database.entities.Merchant
|
||||||
|
import cy.agorise.bitsybitshareswallet.repositories.MerchantRepository
|
||||||
|
|
||||||
|
class MerchantViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
private var mMerchantRepository = MerchantRepository(application)
|
||||||
|
|
||||||
|
internal fun getAllMerchants(): LiveData<List<Merchant>> {
|
||||||
|
return mMerchantRepository.getAll()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue