From 8284ee3e64d3dad1f4e8d3d9875735bf1225ff23 Mon Sep 17 00:00:00 2001 From: Joaquim Ley Date: Sun, 1 Apr 2018 18:59:24 +0200 Subject: [PATCH] Migrate from RecyclerView.Adpater to ListAdapter (from v7 27.1.0 This _new_ ListAdapter gives RecyclerView animations for free, only need to implement some diffUtils in order for the view to know which view(s) to update. --- .../gradle/wrapper/gradle-wrapper.properties | 4 +- .../di/module/FavouriteFragmentModule.kt | 6 +- .../transporteta/home/HomeActivity.kt | 1 - .../home/favorite/FavoriteViewDiffCallback.kt | 14 +++ .../home/favorite/FavoritesViewModel.kt | 18 +-- ...actory.kt => FavoritesViewModelFactory.kt} | 2 +- .../home/favorite/FavouritesAdapter.kt | 118 +++++++++--------- .../home/favorite/FavouritesFragment.kt | 20 +-- .../joaquimley/transporteta/model/Favorite.kt | 3 + .../{FavouriteView.kt => FavoriteView.kt} | 2 +- .../transporteta/sms/SmsController.kt | 13 ++ transport-eta-android/versions.gradle | 10 +- 12 files changed, 121 insertions(+), 90 deletions(-) create mode 100644 transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoriteViewDiffCallback.kt rename transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/{FavouritesViewModelFactory.kt => FavoritesViewModelFactory.kt} (82%) create mode 100644 transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/Favorite.kt rename transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/{FavouriteView.kt => FavoriteView.kt} (55%) diff --git a/transport-eta-android/gradle/wrapper/gradle-wrapper.properties b/transport-eta-android/gradle/wrapper/gradle-wrapper.properties index 3f5667b..9bfd0b8 100644 --- a/transport-eta-android/gradle/wrapper/gradle-wrapper.properties +++ b/transport-eta-android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Mar 24 15:16:17 CET 2018 +#Sun Apr 01 18:04:13 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/di/module/FavouriteFragmentModule.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/di/module/FavouriteFragmentModule.kt index d2e4a68..4444a7e 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/di/module/FavouriteFragmentModule.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/di/module/FavouriteFragmentModule.kt @@ -1,6 +1,6 @@ package com.joaquimley.transporteta.di.module -import com.joaquimley.transporteta.home.favorite.FavouritesViewModelFactory +import com.joaquimley.transporteta.home.favorite.FavoritesViewModelFactory import com.joaquimley.transporteta.sms.SmsController import dagger.Module import dagger.Provides @@ -9,7 +9,7 @@ import dagger.Provides class FavouriteFragmentModule { @Provides - fun provideFavouritesViewModelFactory(smsController: SmsController): FavouritesViewModelFactory { - return FavouritesViewModelFactory(smsController) + fun provideFavouritesViewModelFactory(smsController: SmsController): FavoritesViewModelFactory { + return FavoritesViewModelFactory(smsController) } } \ No newline at end of file diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/HomeActivity.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/HomeActivity.kt index 987a5af..5cf3691 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/HomeActivity.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/HomeActivity.kt @@ -45,7 +45,6 @@ class HomeActivity : AppCompatActivity(), HasSupportFragmentInjector/*, BottomNa viewModel = ViewModelProviders.of(this).get(HomeViewModel::class.java) } - /** * Runtime permission shenanigans */ diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoriteViewDiffCallback.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoriteViewDiffCallback.kt new file mode 100644 index 0000000..6c6e035 --- /dev/null +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoriteViewDiffCallback.kt @@ -0,0 +1,14 @@ +package com.joaquimley.transporteta.home.favorite + +import android.support.v7.util.DiffUtil +import com.joaquimley.transporteta.model.FavoriteView + +class FavoriteViewDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: FavoriteView?, newItem: FavoriteView?): Boolean { + return oldItem?.code == newItem?.code + } + + override fun areContentsTheSame(oldItem: FavoriteView?, newItem: FavoriteView?): Boolean { + return oldItem == newItem + } +} \ No newline at end of file diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModel.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModel.kt index 913e1d9..6abe9b7 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModel.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModel.kt @@ -4,7 +4,7 @@ import android.arch.lifecycle.LiveData import android.arch.lifecycle.MutableLiveData import android.arch.lifecycle.ViewModel import android.util.Log -import com.joaquimley.transporteta.model.FavouriteView +import com.joaquimley.transporteta.model.FavoriteView import com.joaquimley.transporteta.model.data.Resource import com.joaquimley.transporteta.model.data.ResourceState import com.joaquimley.transporteta.sms.SmsController @@ -14,25 +14,25 @@ import com.joaquimley.transporteta.sms.SmsController */ class FavoritesViewModel(val smsController: SmsController) : ViewModel() { - val favouritesLiveData = MutableLiveData>>() + val favouritesLiveData = MutableLiveData>>() init { smsController.serviceSms.subscribe { Log.e("FavoritesViewModel", "SmsController received sms $it") - // TODO: Make it more 🎨 - val currentValue = ArrayList() - currentValue.add(FavouriteView(it.code, it.message)) + // TODO: remove mocked up shenenigans Make it more 🎨 + val currentValue = ArrayList() + currentValue.add(FavoriteView(it.code, it.message)) // val currentValue = favouritesLiveData.value?.data?.toMutableList() -// ?: emptyList() -// currentValue.toMutableList().add(FavouriteView(it.code, it.message)) +// ?: emptyList() +// currentValue.toMutableList().add(FavoriteView(it.code, it.message)) favouritesLiveData.setValue(Resource(ResourceState.SUCCESS, currentValue)) } } - fun getFavourites(): LiveData>> { + fun getFavourites(): LiveData>> { return favouritesLiveData } @@ -41,7 +41,7 @@ class FavoritesViewModel(val smsController: SmsController) : ViewModel() { } - fun onEtaRequested(favourite: FavouriteView) { + fun onEtaRequested(favourite: FavoriteView) { requestEta(favourite.code) } diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesViewModelFactory.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModelFactory.kt similarity index 82% rename from transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesViewModelFactory.kt rename to transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModelFactory.kt index ae69ccd..34bd57b 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesViewModelFactory.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavoritesViewModelFactory.kt @@ -4,7 +4,7 @@ import android.arch.lifecycle.ViewModel import android.arch.lifecycle.ViewModelProvider import com.joaquimley.transporteta.sms.SmsController -class FavouritesViewModelFactory(val smsController: SmsController): ViewModelProvider.Factory { +class FavoritesViewModelFactory(private val smsController: SmsController): ViewModelProvider.Factory { override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(FavoritesViewModel::class.java)) { return FavoritesViewModel(smsController) as T diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesAdapter.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesAdapter.kt index aa55124..1eeaf99 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesAdapter.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/home/favorite/FavouritesAdapter.kt @@ -1,5 +1,6 @@ package com.joaquimley.transporteta.home.favorite +import android.support.v7.recyclerview.extensions.ListAdapter import android.support.v7.widget.AppCompatButton import android.support.v7.widget.AppCompatImageView import android.support.v7.widget.AppCompatTextView @@ -9,61 +10,62 @@ import android.view.View import android.view.ViewGroup import com.bumptech.glide.Glide import com.joaquimley.transporteta.R -import com.joaquimley.transporteta.model.FavouriteView +import com.joaquimley.transporteta.model.FavoriteView import kotterknife.bindView -class FavouritesAdapter(val listener: Listener? = null) : RecyclerView.Adapter() { - - val dataSet: MutableList = emptyList().toMutableList() - - init { - setHasStableIds(true) - } - - fun set(favourites: List) { - dataSet.clear() - dataSet.addAll(favourites) - notifyDataSetChanged() - } - - fun add(favourites: List) { - val index = dataSet.size - dataSet.addAll(favourites) - notifyItemRangeInserted(index, favourites.size) - } - - fun addLoadingView() { - val index = dataSet.size - if (dataSet.isEmpty().not() && dataSet[index] != null) { - dataSet.add(null) - notifyItemInserted(index + 1) - } - } - - fun removeLoadingView() { - val lastIndex = dataSet.size - 1 - if (dataSet.isEmpty().not() && dataSet[lastIndex] == null) { - dataSet.removeAt(lastIndex) - notifyItemRemoved(lastIndex) - } - } - +class FavouritesAdapter(private val clickListener: (FavoriteView) -> Unit) + : ListAdapter(FavoriteViewDiffCallback()) { + +// val dataSet: MutableList = emptyList().toMutableList() +// +// init { +// setHasStableIds(true) +// } +// +// fun set(favourites: List) { +// dataSet.clear() +// dataSet.addAll(favourites) +// notifyDataSetChanged() +// } +// +// fun add(favourites: List) { +// val index = dataSet.size +// dataSet.addAll(favourites) +// notifyItemRangeInserted(index, favourites.size) +// } +// +// fun addLoadingView() { +// val index = dataSet.size +// if (dataSet.isEmpty().not() && dataSet[index] != null) { +// dataSet.add(null) +// notifyItemInserted(index + 1) +// } +// } +// +// fun removeLoadingView() { +// val lastIndex = dataSet.size - 1 +// if (dataSet.isEmpty().not() && dataSet[lastIndex] == null) { +// dataSet.removeAt(lastIndex) +// notifyItemRemoved(lastIndex) +// } +// } +// fun isEmpty() = itemCount == 0 - - override fun getItemCount(): Int { - return dataSet.size - } - - override fun getItemId(position: Int): Long { - return if (dataSet.size >= position) { - dataSet[position]?.code?.toLong() ?: View.NO_ID.toLong() - } else { - View.NO_ID.toLong() - } - } +// +// override fun getItemCount(): Int { +// return dataSet.size +// } +// +// override fun getItemId(position: Int): Long { +// return if (dataSet.size >= position) { +// dataSet[position]?.code?.toLong() ?: View.NO_ID.toLong() +// } else { +// View.NO_ID.toLong() +// } +// } override fun getItemViewType(position: Int): Int { - return if (dataSet.size >= position && dataSet[position] != null) { + return if (getItem(position) != null) { VIEW_TYPE_FAVORITE } else { VIEW_TYPE_PROGRESS @@ -73,7 +75,7 @@ class FavouritesAdapter(val listener: Listener? = null) : RecyclerView.Adapter { - FavouriteViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_favorite, parent, false)) + FavoriteViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_favorite, parent, false)) } else -> { ProgressViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_progress, parent, false)) @@ -82,27 +84,27 @@ class FavouritesAdapter(val listener: Listener? = null) : RecyclerView.Adapter?, + private fun handleDataState(resourceState: ResourceState, data: List?, message: String?) { when (resourceState) { ResourceState.LOADING -> setupScreenForLoadingState(true) @@ -101,15 +101,15 @@ class FavouritesFragment : Fragment(), FavouritesAdapter.Listener { } else { swipeRefreshView.isRefreshing = false contentLoadingView.visibility = View.GONE - adapter.removeLoadingView() +// adapter.removeLoadingView() } } - private fun setupScreenForSuccess(favouriteViewList: List?) { + private fun setupScreenForSuccess(favoriteViewList: List?) { setupScreenForLoadingState(false) setupScreenEmptyState(false) - if (favouriteViewList != null) { - adapter.set(favouriteViewList) + if (favoriteViewList != null) { + adapter.submitList(favoriteViewList) } } @@ -133,7 +133,7 @@ class FavouritesFragment : Fragment(), FavouritesAdapter.Listener { private fun setupRecyclerView() { recyclerView.setHasFixedSize(true) recyclerView.layoutManager = LinearLayoutManager(context) - adapter = FavouritesAdapter(this) + adapter = FavouritesAdapter({viewModel.onEtaRequested(it)}) recyclerView.adapter = adapter } diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/Favorite.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/Favorite.kt new file mode 100644 index 0000000..5962401 --- /dev/null +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/Favorite.kt @@ -0,0 +1,3 @@ +package com.joaquimley.transporteta.model + +class Favoritedata (val code: Int = -1, val latestEta: String = "") \ No newline at end of file diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/FavouriteView.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/FavoriteView.kt similarity index 55% rename from transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/FavouriteView.kt rename to transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/FavoriteView.kt index 3445de8..84d7d2c 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/FavouriteView.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/model/FavoriteView.kt @@ -3,4 +3,4 @@ package com.joaquimley.transporteta.model /** * Created by joaquimley on 28/03/2018. */ -data class FavouriteView(val code: Int = -1, val latestEta: String = "") \ No newline at end of file +data class FavoriteView(val code: Int = -1, val latestEta: String = "") \ No newline at end of file diff --git a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/sms/SmsController.kt b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/sms/SmsController.kt index 29f9a51..d3f4934 100644 --- a/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/sms/SmsController.kt +++ b/transport-eta-android/mobile-ui/src/main/java/com/joaquimley/transporteta/sms/SmsController.kt @@ -45,6 +45,16 @@ class SmsController @Inject constructor(private val smsBroadcastReceiver: SmsBro /** +--------------------------------- +Send SMS to 3599 with the format: +--------------------------------- + +C (SPACE) Bus_stop_code + +--------------------- +Sms response example: +--------------------- + SMS@Carris 759 ORIENTE ::14:52 [02m]:: @@ -55,8 +65,11 @@ SMS@Carris 759 ORIENTE ::15:18 [28m]:: +---------------- + Para consultar tempos de espera (em minutos), relativamente a todos os veículos que passam numa determinada paragem: Deverá digitar C (espaço) Código da Paragem e enviar para o 3599 (custo de mensagem escrita normal); + Para consultar tempos de espera dos próximos três veículos de uma carreira, numa determinada paragem: Deverá digitar C (espaço) Código da Paragem (espaço) Nº da Carreira e enviar para o 3599 (custo de mensagem escrita normal) diff --git a/transport-eta-android/versions.gradle b/transport-eta-android/versions.gradle index 2690d4f..0d0dfba 100644 --- a/transport-eta-android/versions.gradle +++ b/transport-eta-android/versions.gradle @@ -4,9 +4,9 @@ **/ ext.deps = [:] def versions = [:] -versions.arch = "1.0.0" -versions.arch_runtime = "1.0.3" -versions.support = "27.0.0" +versions.arch = "1.1.1" +versions.arch_room = "1.0.0" +versions.support = "27.1.0" versions.support_constraint = "1.0.2" versions.dagger = "2.11" versions.javax_inject = "1" @@ -63,10 +63,10 @@ room.testing = "android.arch.persistence.room:testing:$versions.arch" deps.room = room def lifecycle = [:] -lifecycle.runtime = "android.arch.lifecycle:runtime:$versions.arch" +lifecycle.runtime = "android.arch.lifecycle:runtime:$versions.arch_room" +lifecycle.compiler = "android.arch.lifecycle:compiler:$versions.arch_room" lifecycle.extensions = "android.arch.lifecycle:extensions:$versions.arch" lifecycle.java8 = "android.arch.lifecycle:common-java8:$versions.arch" -lifecycle.compiler = "android.arch.lifecycle:compiler:$versions.arch" deps.lifecycle = lifecycle def arch_core = [:]