Skip to content

Commit 608a8b4

Browse files
Migrated to Paging 3
1 parent fb11bc0 commit 608a8b4

21 files changed

+275
-363
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A simple Android MVVM pattern example and template.
44

55
## Android Studio Version
66

7-
- Android Studio Arctic Fox | 2020.3.1 RC 1
7+
- Android Studio Arctic Fox | 2020.3.1 Patch 2
88

99
## Used Components/Libraries
1010

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

2727
## Others
@@ -56,13 +56,13 @@ A simple Android MVVM pattern example and template.
5656
- `SharedPref`
5757
- `AlarmUtils`
5858
- `LocationProviderUtilClient`
59+
- `Event` Class
5960

6061
## Todo
6162

6263
- Add New Post
6364
- Demo Login
6465
- Demo Registration
65-
- Migrate to Paging 3
6666
- OneSignal integration
6767
- Splash (Introduced in Android S)
6868
- Testing

app/src/main/java/org/imaginativeworld/simplemvvm/adapters/DemoPostListAdapter.kt

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,27 @@ import android.view.ViewGroup
55
import androidx.recyclerview.widget.DiffUtil
66
import androidx.recyclerview.widget.ListAdapter
77
import androidx.recyclerview.widget.RecyclerView
8+
import coil.load
9+
import coil.transform.RoundedCornersTransformation
810
import org.imaginativeworld.simplemvvm.databinding.DemoItemPostBinding
911
import org.imaginativeworld.simplemvvm.interfaces.BindableAdapter
1012
import org.imaginativeworld.simplemvvm.interfaces.OnObjectListInteractionListener
11-
import org.imaginativeworld.simplemvvm.models.DemoPostResult
13+
import org.imaginativeworld.simplemvvm.models.DemoPost
14+
import org.imaginativeworld.simplemvvm.utils.extensions.dpToPx
1215

1316
class DemoPostListAdapter(
14-
private val listener: OnObjectListInteractionListener<DemoPostResult>
15-
) : ListAdapter<DemoPostResult, DemoPostListAdapter.ListViewHolder>(DIFF_CALLBACK),
16-
BindableAdapter<List<DemoPostResult>> {
17+
private val listener: OnObjectListInteractionListener<DemoPost>
18+
) : ListAdapter<DemoPost, DemoPostListAdapter.ListViewHolder>(DIFF_CALLBACK),
19+
BindableAdapter<List<DemoPost>> {
1720

1821
companion object {
1922

20-
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<DemoPostResult>() {
21-
override fun areItemsTheSame(oldItem: DemoPostResult, newItem: DemoPostResult): Boolean {
23+
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<DemoPost>() {
24+
override fun areItemsTheSame(oldItem: DemoPost, newItem: DemoPost): Boolean {
2225
return oldItem.id == newItem.id
2326
}
2427

25-
override fun areContentsTheSame(oldItem: DemoPostResult, newItem: DemoPostResult): Boolean {
28+
override fun areContentsTheSame(oldItem: DemoPost, newItem: DemoPost): Boolean {
2629
return oldItem == newItem
2730
}
2831
}
@@ -38,7 +41,7 @@ class DemoPostListAdapter(
3841
holder.bind(item)
3942
}
4043

41-
override fun setItems(data: List<DemoPostResult>?) {
44+
override fun setItems(data: List<DemoPost>?) {
4245
submitList(data) {
4346
data?.apply {
4447
checkEmptiness()
@@ -56,27 +59,34 @@ class DemoPostListAdapter(
5659

5760
class ListViewHolder private constructor(
5861
private val binding: DemoItemPostBinding,
59-
private val listener: OnObjectListInteractionListener<DemoPostResult>
62+
private val listener: OnObjectListInteractionListener<DemoPost>
6063
) : RecyclerView.ViewHolder(binding.root) {
6164

62-
fun bind(item: DemoPostResult) {
65+
fun bind(item: DemoPost) {
6366
binding.post = item
6467
binding.executePendingBindings()
6568

69+
// Image
70+
val imageUrl = "https://picsum.photos/seed/${item.id}/128"
71+
binding.img.load(imageUrl) {
72+
crossfade(true)
73+
transformations(RoundedCornersTransformation(8.dpToPx().toFloat()))
74+
}
75+
6676
binding.root.setOnClickListener {
67-
listener.onClick(adapterPosition, item)
77+
listener.onClick(bindingAdapterPosition, item)
6878
}
6979

7080
binding.root.setOnLongClickListener {
71-
listener.onLongClick(adapterPosition, item)
81+
listener.onLongClick(bindingAdapterPosition, item)
7282
true
7383
}
7484
}
7585

7686
companion object {
7787
fun from(
7888
parent: ViewGroup,
79-
listener: OnObjectListInteractionListener<DemoPostResult>
89+
listener: OnObjectListInteractionListener<DemoPost>
8090
): ListViewHolder {
8191
val layoutInflater = LayoutInflater.from(parent.context)
8292
val binding = DemoItemPostBinding.inflate(layoutInflater, parent, false)

app/src/main/java/org/imaginativeworld/simplemvvm/adapters/DemoPostPagedListAdapter.kt

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ package org.imaginativeworld.simplemvvm.adapters
33
import android.graphics.Color
44
import android.view.LayoutInflater
55
import android.view.ViewGroup
6-
import androidx.paging.PagedList
7-
import androidx.paging.PagedListAdapter
6+
import androidx.paging.PagingDataAdapter
87
import androidx.recyclerview.widget.DiffUtil
98
import androidx.recyclerview.widget.RecyclerView
109
import coil.load
@@ -13,32 +12,29 @@ import kotlinx.coroutines.CoroutineScope
1312
import kotlinx.coroutines.Dispatchers
1413
import kotlinx.coroutines.launch
1514
import org.imaginativeworld.simplemvvm.databinding.DemoItemPostBinding
16-
import org.imaginativeworld.simplemvvm.interfaces.BindableAdapter
1715
import org.imaginativeworld.simplemvvm.interfaces.OnObjectListInteractionListener
18-
import org.imaginativeworld.simplemvvm.models.DemoPostResult
16+
import org.imaginativeworld.simplemvvm.models.DemoPost
1917
import org.imaginativeworld.simplemvvm.utils.calculatePaletteInImage
2018
import org.imaginativeworld.simplemvvm.utils.extensions.dpToPx
21-
import timber.log.Timber
2219

2320
class DemoPostPagedListAdapter(
24-
private val listener: OnObjectListInteractionListener<DemoPostResult>
25-
) : PagedListAdapter<DemoPostResult, DemoPostPagedListAdapter.ListViewHolder>(DIFF_CALLBACK),
26-
BindableAdapter<PagedList<DemoPostResult>> {
21+
private val listener: OnObjectListInteractionListener<DemoPost>
22+
) : PagingDataAdapter<DemoPost, DemoPostPagedListAdapter.ListViewHolder>(DIFF_CALLBACK) {
2723

2824
companion object {
2925

3026
private val DIFF_CALLBACK = object :
31-
DiffUtil.ItemCallback<DemoPostResult>() {
27+
DiffUtil.ItemCallback<DemoPost>() {
3228
override fun areItemsTheSame(
33-
oldItem: DemoPostResult,
34-
newItem: DemoPostResult
29+
oldItem: DemoPost,
30+
newItem: DemoPost
3531
): Boolean {
3632
return oldItem.id == newItem.id
3733
}
3834

3935
override fun areContentsTheSame(
40-
oldItem: DemoPostResult,
41-
newItem: DemoPostResult
36+
oldItem: DemoPost,
37+
newItem: DemoPost
4238
): Boolean {
4339
return oldItem == newItem
4440
}
@@ -56,35 +52,18 @@ class DemoPostPagedListAdapter(
5652
holder.bind(item)
5753
}
5854

59-
override fun setItems(data: PagedList<DemoPostResult>?) {
60-
submitList(data) {
61-
data?.apply {
62-
checkEmptiness()
63-
}
64-
}
65-
}
66-
67-
private fun checkEmptiness() {
68-
if (itemCount > 0) {
69-
listener.hideEmptyView()
70-
} else {
71-
listener.showEmptyView()
72-
}
73-
}
74-
75-
7655
class ListViewHolder private constructor(
7756
private val binding: DemoItemPostBinding,
78-
private val listener: OnObjectListInteractionListener<DemoPostResult>
57+
private val listener: OnObjectListInteractionListener<DemoPost>
7958
) : RecyclerView.ViewHolder(binding.root) {
8059

81-
fun bind(item: DemoPostResult?) {
60+
fun bind(item: DemoPost?) {
8261
item?.also { _item ->
8362
binding.post = _item
8463
binding.executePendingBindings()
8564

8665
// Image
87-
val imageUrl = "https://picsum.photos/200?$bindingAdapterPosition"
66+
val imageUrl = "https://picsum.photos/seed/${_item.id}/128"
8867
binding.img.load(imageUrl) {
8968
crossfade(true)
9069
transformations(RoundedCornersTransformation(8.dpToPx().toFloat()))
@@ -106,8 +85,6 @@ class DemoPostPagedListAdapter(
10685
context = binding.root.context,
10786
imageUrl = imageUrl
10887
)?.let { swatch ->
109-
Timber.e("position: $position | bindingAdapterPosition: $bindingAdapterPosition")
110-
11188
if (position == bindingAdapterPosition) {
11289
binding.root.setBackgroundColor(
11390
swatch.rgb
@@ -136,11 +113,11 @@ class DemoPostPagedListAdapter(
136113
companion object {
137114
fun from(
138115
parent: ViewGroup,
139-
listener: OnObjectListInteractionListener<DemoPostResult>
140-
): DemoPostPagedListAdapter.ListViewHolder {
116+
listener: OnObjectListInteractionListener<DemoPost>
117+
): ListViewHolder {
141118
val layoutInflater = LayoutInflater.from(parent.context)
142119
val binding = DemoItemPostBinding.inflate(layoutInflater, parent, false)
143-
return DemoPostPagedListAdapter.ListViewHolder(binding, listener)
120+
return ListViewHolder(binding, listener)
144121
}
145122
}
146123

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.imaginativeworld.simplemvvm.adapters
2+
3+
import android.view.LayoutInflater
4+
import android.view.ViewGroup
5+
import androidx.core.view.isVisible
6+
import androidx.paging.LoadState
7+
import androidx.paging.LoadStateAdapter
8+
import androidx.recyclerview.widget.RecyclerView
9+
import org.imaginativeworld.simplemvvm.databinding.DemoLoadStateFooterViewItemBinding
10+
11+
class DemoPostPagedLoadStateAdapter(
12+
private val retry: () -> Unit
13+
) : LoadStateAdapter<DemoPostPagedLoadStateAdapter.ItemViewHolder>() {
14+
15+
override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): ItemViewHolder {
16+
return ItemViewHolder.from(parent, retry)
17+
}
18+
19+
override fun onBindViewHolder(holder: ItemViewHolder, loadState: LoadState) {
20+
holder.bind(loadState)
21+
}
22+
23+
class ItemViewHolder private constructor(
24+
private val binding: DemoLoadStateFooterViewItemBinding,
25+
retry: () -> Unit
26+
) : RecyclerView.ViewHolder(binding.root) {
27+
28+
init {
29+
binding.retryButton.setOnClickListener { retry.invoke() }
30+
}
31+
32+
fun bind(loadState: LoadState) {
33+
if (loadState is LoadState.Error) {
34+
binding.errorMsg.text = loadState.error.localizedMessage
35+
}
36+
binding.progressBar.isVisible = loadState is LoadState.Loading
37+
binding.retryButton.isVisible = loadState is LoadState.Error
38+
binding.errorMsg.isVisible = loadState is LoadState.Error
39+
}
40+
41+
companion object {
42+
fun from(
43+
parent: ViewGroup,
44+
retry: () -> Unit
45+
): ItemViewHolder {
46+
val layoutInflater = LayoutInflater.from(parent.context)
47+
val binding =
48+
DemoLoadStateFooterViewItemBinding.inflate(layoutInflater, parent, false)
49+
return ItemViewHolder(binding, retry)
50+
}
51+
}
52+
53+
}
54+
}

app/src/main/java/org/imaginativeworld/simplemvvm/adapters/DemoUserListAdapter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ class DemoUserListAdapter(
6666
binding.user = item
6767
binding.executePendingBindings()
6868
binding.root.setOnClickListener {
69-
listener.onClick(adapterPosition, item)
69+
listener.onClick(bindingAdapterPosition, item)
7070
}
7171
binding.root.setOnLongClickListener {
72-
listener.onLongClick(adapterPosition, item)
72+
listener.onLongClick(bindingAdapterPosition, item)
7373

7474
true
7575
}

app/src/main/java/org/imaginativeworld/simplemvvm/datasource/PostPagedDataSource.kt

Lines changed: 0 additions & 77 deletions
This file was deleted.

0 commit comments

Comments
 (0)