Skip to content

Commit

Permalink
Migrated to Paging 3
Browse files Browse the repository at this point in the history
  • Loading branch information
ImaginativeShohag committed Sep 6, 2021
1 parent fb11bc0 commit 608a8b4
Show file tree
Hide file tree
Showing 21 changed files with 275 additions and 363 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ A simple Android MVVM pattern example and template.

## Android Studio Version

- Android Studio Arctic Fox | 2020.3.1 RC 1
- Android Studio Arctic Fox | 2020.3.1 Patch 2

## Used Components/Libraries

Expand All @@ -20,8 +20,8 @@ A simple Android MVVM pattern example and template.
- Timber (https://github.com/JakeWharton/timber)
- Custom Fonts (https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml)
- Shimmer for Android (https://github.com/facebook/shimmer-android)
- Dagger-Hilt (https://github.com/google/dagger)
- Paging (https://developer.android.com/topic/libraries/architecture/paging)
- Hilt (https://dagger.dev/hilt/)
- Paging 3 (https://developer.android.com/topic/libraries/architecture/paging)
- Dexter (https://github.com/Karumi/Dexter) **(coming soon...)**

## Others
Expand Down Expand Up @@ -56,13 +56,13 @@ A simple Android MVVM pattern example and template.
- `SharedPref`
- `AlarmUtils`
- `LocationProviderUtilClient`
- `Event` Class

## Todo

- Add New Post
- Demo Login
- Demo Registration
- Migrate to Paging 3
- OneSignal integration
- Splash (Introduced in Android S)
- Testing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,27 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import coil.load
import coil.transform.RoundedCornersTransformation
import org.imaginativeworld.simplemvvm.databinding.DemoItemPostBinding
import org.imaginativeworld.simplemvvm.interfaces.BindableAdapter
import org.imaginativeworld.simplemvvm.interfaces.OnObjectListInteractionListener
import org.imaginativeworld.simplemvvm.models.DemoPostResult
import org.imaginativeworld.simplemvvm.models.DemoPost
import org.imaginativeworld.simplemvvm.utils.extensions.dpToPx

class DemoPostListAdapter(
private val listener: OnObjectListInteractionListener<DemoPostResult>
) : ListAdapter<DemoPostResult, DemoPostListAdapter.ListViewHolder>(DIFF_CALLBACK),
BindableAdapter<List<DemoPostResult>> {
private val listener: OnObjectListInteractionListener<DemoPost>
) : ListAdapter<DemoPost, DemoPostListAdapter.ListViewHolder>(DIFF_CALLBACK),
BindableAdapter<List<DemoPost>> {

companion object {

private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<DemoPostResult>() {
override fun areItemsTheSame(oldItem: DemoPostResult, newItem: DemoPostResult): Boolean {
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<DemoPost>() {
override fun areItemsTheSame(oldItem: DemoPost, newItem: DemoPost): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: DemoPostResult, newItem: DemoPostResult): Boolean {
override fun areContentsTheSame(oldItem: DemoPost, newItem: DemoPost): Boolean {
return oldItem == newItem
}
}
Expand All @@ -38,7 +41,7 @@ class DemoPostListAdapter(
holder.bind(item)
}

override fun setItems(data: List<DemoPostResult>?) {
override fun setItems(data: List<DemoPost>?) {
submitList(data) {
data?.apply {
checkEmptiness()
Expand All @@ -56,27 +59,34 @@ class DemoPostListAdapter(

class ListViewHolder private constructor(
private val binding: DemoItemPostBinding,
private val listener: OnObjectListInteractionListener<DemoPostResult>
private val listener: OnObjectListInteractionListener<DemoPost>
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: DemoPostResult) {
fun bind(item: DemoPost) {
binding.post = item
binding.executePendingBindings()

// Image
val imageUrl = "https://picsum.photos/seed/${item.id}/128"
binding.img.load(imageUrl) {
crossfade(true)
transformations(RoundedCornersTransformation(8.dpToPx().toFloat()))
}

binding.root.setOnClickListener {
listener.onClick(adapterPosition, item)
listener.onClick(bindingAdapterPosition, item)
}

binding.root.setOnLongClickListener {
listener.onLongClick(adapterPosition, item)
listener.onLongClick(bindingAdapterPosition, item)
true
}
}

companion object {
fun from(
parent: ViewGroup,
listener: OnObjectListInteractionListener<DemoPostResult>
listener: OnObjectListInteractionListener<DemoPost>
): ListViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = DemoItemPostBinding.inflate(layoutInflater, parent, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ package org.imaginativeworld.simplemvvm.adapters
import android.graphics.Color
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.paging.PagedList
import androidx.paging.PagedListAdapter
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import coil.load
Expand All @@ -13,32 +12,29 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.imaginativeworld.simplemvvm.databinding.DemoItemPostBinding
import org.imaginativeworld.simplemvvm.interfaces.BindableAdapter
import org.imaginativeworld.simplemvvm.interfaces.OnObjectListInteractionListener
import org.imaginativeworld.simplemvvm.models.DemoPostResult
import org.imaginativeworld.simplemvvm.models.DemoPost
import org.imaginativeworld.simplemvvm.utils.calculatePaletteInImage
import org.imaginativeworld.simplemvvm.utils.extensions.dpToPx
import timber.log.Timber

class DemoPostPagedListAdapter(
private val listener: OnObjectListInteractionListener<DemoPostResult>
) : PagedListAdapter<DemoPostResult, DemoPostPagedListAdapter.ListViewHolder>(DIFF_CALLBACK),
BindableAdapter<PagedList<DemoPostResult>> {
private val listener: OnObjectListInteractionListener<DemoPost>
) : PagingDataAdapter<DemoPost, DemoPostPagedListAdapter.ListViewHolder>(DIFF_CALLBACK) {

companion object {

private val DIFF_CALLBACK = object :
DiffUtil.ItemCallback<DemoPostResult>() {
DiffUtil.ItemCallback<DemoPost>() {
override fun areItemsTheSame(
oldItem: DemoPostResult,
newItem: DemoPostResult
oldItem: DemoPost,
newItem: DemoPost
): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(
oldItem: DemoPostResult,
newItem: DemoPostResult
oldItem: DemoPost,
newItem: DemoPost
): Boolean {
return oldItem == newItem
}
Expand All @@ -56,35 +52,18 @@ class DemoPostPagedListAdapter(
holder.bind(item)
}

override fun setItems(data: PagedList<DemoPostResult>?) {
submitList(data) {
data?.apply {
checkEmptiness()
}
}
}

private fun checkEmptiness() {
if (itemCount > 0) {
listener.hideEmptyView()
} else {
listener.showEmptyView()
}
}


class ListViewHolder private constructor(
private val binding: DemoItemPostBinding,
private val listener: OnObjectListInteractionListener<DemoPostResult>
private val listener: OnObjectListInteractionListener<DemoPost>
) : RecyclerView.ViewHolder(binding.root) {

fun bind(item: DemoPostResult?) {
fun bind(item: DemoPost?) {
item?.also { _item ->
binding.post = _item
binding.executePendingBindings()

// Image
val imageUrl = "https://picsum.photos/200?$bindingAdapterPosition"
val imageUrl = "https://picsum.photos/seed/${_item.id}/128"
binding.img.load(imageUrl) {
crossfade(true)
transformations(RoundedCornersTransformation(8.dpToPx().toFloat()))
Expand All @@ -106,8 +85,6 @@ class DemoPostPagedListAdapter(
context = binding.root.context,
imageUrl = imageUrl
)?.let { swatch ->
Timber.e("position: $position | bindingAdapterPosition: $bindingAdapterPosition")

if (position == bindingAdapterPosition) {
binding.root.setBackgroundColor(
swatch.rgb
Expand Down Expand Up @@ -136,11 +113,11 @@ class DemoPostPagedListAdapter(
companion object {
fun from(
parent: ViewGroup,
listener: OnObjectListInteractionListener<DemoPostResult>
): DemoPostPagedListAdapter.ListViewHolder {
listener: OnObjectListInteractionListener<DemoPost>
): ListViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding = DemoItemPostBinding.inflate(layoutInflater, parent, false)
return DemoPostPagedListAdapter.ListViewHolder(binding, listener)
return ListViewHolder(binding, listener)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.imaginativeworld.simplemvvm.adapters

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.view.isVisible
import androidx.paging.LoadState
import androidx.paging.LoadStateAdapter
import androidx.recyclerview.widget.RecyclerView
import org.imaginativeworld.simplemvvm.databinding.DemoLoadStateFooterViewItemBinding

class DemoPostPagedLoadStateAdapter(
private val retry: () -> Unit
) : LoadStateAdapter<DemoPostPagedLoadStateAdapter.ItemViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): ItemViewHolder {
return ItemViewHolder.from(parent, retry)
}

override fun onBindViewHolder(holder: ItemViewHolder, loadState: LoadState) {
holder.bind(loadState)
}

class ItemViewHolder private constructor(
private val binding: DemoLoadStateFooterViewItemBinding,
retry: () -> Unit
) : RecyclerView.ViewHolder(binding.root) {

init {
binding.retryButton.setOnClickListener { retry.invoke() }
}

fun bind(loadState: LoadState) {
if (loadState is LoadState.Error) {
binding.errorMsg.text = loadState.error.localizedMessage
}
binding.progressBar.isVisible = loadState is LoadState.Loading
binding.retryButton.isVisible = loadState is LoadState.Error
binding.errorMsg.isVisible = loadState is LoadState.Error
}

companion object {
fun from(
parent: ViewGroup,
retry: () -> Unit
): ItemViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding =
DemoLoadStateFooterViewItemBinding.inflate(layoutInflater, parent, false)
return ItemViewHolder(binding, retry)
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ class DemoUserListAdapter(
binding.user = item
binding.executePendingBindings()
binding.root.setOnClickListener {
listener.onClick(adapterPosition, item)
listener.onClick(bindingAdapterPosition, item)
}
binding.root.setOnLongClickListener {
listener.onLongClick(adapterPosition, item)
listener.onLongClick(bindingAdapterPosition, item)

true
}
Expand Down

This file was deleted.

Loading

0 comments on commit 608a8b4

Please sign in to comment.