Skip to content

Commit 7338147

Browse files
Okuro3499dogi
andauthored
surveys: smoother adapters (fixes #4493) (#4495)
Co-authored-by: dogi <[email protected]>
1 parent 772881b commit 7338147

File tree

3 files changed

+125
-60
lines changed

3 files changed

+125
-60
lines changed

Diff for: app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ android {
1010
applicationId "org.ole.planet.myplanet"
1111
minSdkVersion 21
1212
targetSdkVersion 34
13-
versionCode 1960
14-
versionName "0.19.60"
13+
versionCode 1961
14+
versionName "0.19.61"
1515
ndkVersion '21.3.6528147'
1616
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1717
vectorDrawables.useSupportLibrary = true

Diff for: app/src/main/java/org/ole/planet/myplanet/ui/survey/AdapterSurvey.kt

+65-37
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.content.Context
44
import android.view.LayoutInflater
55
import android.view.View
66
import android.view.ViewGroup
7+
import androidx.recyclerview.widget.DiffUtil
78
import androidx.recyclerview.widget.RecyclerView
89
import io.realm.Realm
910
import org.ole.planet.myplanet.R
@@ -13,65 +14,92 @@ import org.ole.planet.myplanet.model.RealmExamQuestion
1314
import org.ole.planet.myplanet.model.RealmStepExam
1415
import org.ole.planet.myplanet.model.RealmSubmission.Companion.getNoOfSubmissionByUser
1516
import org.ole.planet.myplanet.model.RealmSubmission.Companion.getRecentSubmissionDate
17+
import org.ole.planet.myplanet.model.RealmUserModel
18+
import org.ole.planet.myplanet.service.UserProfileDbHandler
1619
import org.ole.planet.myplanet.ui.submission.AdapterMySubmission
17-
import org.ole.planet.myplanet.ui.survey.AdapterSurvey.ViewHolderSurvey
1820
import org.ole.planet.myplanet.utilities.TimeUtils.formatDate
19-
import org.ole.planet.myplanet.service.UserProfileDbHandler
20-
import org.ole.planet.myplanet.model.RealmUserModel
2121

22-
class AdapterSurvey(private val context: Context, private val examList: List<RealmStepExam>, private val mRealm: Realm, private val userId: String) : RecyclerView.Adapter<ViewHolderSurvey>() {
23-
private lateinit var rowSurveyBinding: RowSurveyBinding
22+
class AdapterSurvey(private val context: Context, private val mRealm: Realm, private val userId: String) : RecyclerView.Adapter<AdapterSurvey.ViewHolderSurvey>() {
23+
private var examList: List<RealmStepExam> = emptyList()
2424
private var listener: OnHomeItemClickListener? = null
25-
var user: RealmUserModel? = null
25+
private var user: RealmUserModel? = null
2626

2727
init {
2828
if (context is OnHomeItemClickListener) {
2929
listener = context
3030
}
31+
user = UserProfileDbHandler(context).userModel
32+
}
33+
34+
fun updateData(newList: List<RealmStepExam>) {
35+
val diffCallback = SurveyDiffCallback(examList, newList)
36+
val diffResult = DiffUtil.calculateDiff(diffCallback)
37+
examList = newList
38+
diffResult.dispatchUpdatesTo(this)
3139
}
3240

3341
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolderSurvey {
34-
rowSurveyBinding = RowSurveyBinding.inflate(LayoutInflater.from(context), parent, false)
35-
return ViewHolderSurvey(rowSurveyBinding)
42+
val binding = RowSurveyBinding.inflate(LayoutInflater.from(parent.context), parent, false)
43+
return ViewHolderSurvey(binding)
3644
}
3745

3846
override fun onBindViewHolder(holder: ViewHolderSurvey, position: Int) {
39-
user = UserProfileDbHandler(context).userModel
40-
rowSurveyBinding.tvTitle.text = examList[position].name
41-
rowSurveyBinding.startSurvey.setOnClickListener {
42-
AdapterMySubmission.openSurvey(listener, examList[position].id, false)
43-
}
44-
val questions: List<RealmExamQuestion> = mRealm.where(RealmExamQuestion::class.java).equalTo("examId", examList[position].id).findAll()
45-
if (questions.isEmpty()) {
46-
rowSurveyBinding.sendSurvey.visibility = View.GONE
47-
rowSurveyBinding.startSurvey.visibility = View.GONE
48-
}
49-
rowSurveyBinding.startSurvey.text = if (examList[position].isFromNation) context.getString(R.string.take_survey) else context.getString(
50-
R.string.record_survey
51-
)
52-
if (user?.id?.startsWith("guest") == true) {
53-
rowSurveyBinding.startSurvey.visibility = View.GONE
54-
}
55-
val noOfSubmission = getNoOfSubmissionByUser(examList[position].id, userId, mRealm)
56-
val subDate = getRecentSubmissionDate(examList[position].id, userId, mRealm)
57-
val createdDate = RealmStepExam.getSurveyCreationTime(examList[position].id!!, mRealm)
58-
rowSurveyBinding.tvNoSubmissions.text = noOfSubmission
59-
rowSurveyBinding.tvDateCompleted.text = subDate
60-
rowSurveyBinding.tvDate.text = formatDate(createdDate!!, "MMM dd, yyyy")
47+
holder.bind(examList[position])
6148
}
6249

63-
override fun getItemCount(): Int {
64-
return examList.size
65-
}
50+
override fun getItemCount(): Int = examList.size
6651

67-
inner class ViewHolderSurvey(rowSurveyBinding: RowSurveyBinding) : RecyclerView.ViewHolder(rowSurveyBinding.root) {
52+
inner class ViewHolderSurvey(private val binding: RowSurveyBinding) : RecyclerView.ViewHolder(binding.root) {
6853
init {
69-
rowSurveyBinding.startSurvey.visibility = View.VISIBLE
70-
rowSurveyBinding.sendSurvey.visibility = View.GONE
71-
rowSurveyBinding.sendSurvey.setOnClickListener {
54+
binding.startSurvey.visibility = View.VISIBLE
55+
binding.sendSurvey.visibility = View.GONE
56+
binding.sendSurvey.setOnClickListener {
7257
val current = examList[bindingAdapterPosition]
7358
listener?.sendSurvey(current)
7459
}
7560
}
61+
62+
fun bind(exam: RealmStepExam) {
63+
binding.apply {
64+
tvTitle.text = exam.name
65+
startSurvey.setOnClickListener {
66+
AdapterMySubmission.openSurvey(listener, exam.id, false)
67+
}
68+
69+
val questions = mRealm.where(RealmExamQuestion::class.java)
70+
.equalTo("examId", exam.id)
71+
.findAll()
72+
73+
if (questions.isEmpty()) {
74+
sendSurvey.visibility = View.GONE
75+
startSurvey.visibility = View.GONE
76+
}
77+
78+
startSurvey.text = if (exam.isFromNation) {
79+
context.getString(R.string.take_survey)
80+
} else {
81+
context.getString(R.string.record_survey)
82+
}
83+
84+
if (user?.id?.startsWith("guest") == true) {
85+
startSurvey.visibility = View.GONE
86+
}
87+
88+
tvNoSubmissions.text = getNoOfSubmissionByUser(exam.id, userId, mRealm)
89+
tvDateCompleted.text = getRecentSubmissionDate(exam.id, userId, mRealm)
90+
tvDate.text = formatDate(RealmStepExam.getSurveyCreationTime(exam.id!!, mRealm)!!, "MMM dd, yyyy")
91+
}
92+
}
93+
}
94+
}
95+
96+
class SurveyDiffCallback(private val oldList: List<RealmStepExam>, private val newList: List<RealmStepExam>) : DiffUtil.Callback() {
97+
override fun getOldListSize(): Int = oldList.size
98+
override fun getNewListSize(): Int = newList.size
99+
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
100+
return oldList[oldItemPosition].id == newList[newItemPosition].id
101+
}
102+
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
103+
return oldList[oldItemPosition] == newList[newItemPosition]
76104
}
77105
}

Diff for: app/src/main/java/org/ole/planet/myplanet/ui/survey/SurveyFragment.kt

+58-21
Original file line numberDiff line numberDiff line change
@@ -16,36 +16,50 @@ class SurveyFragment : BaseRecyclerFragment<RealmStepExam?>() {
1616
private lateinit var addNewSurvey: FloatingActionButton
1717
private lateinit var spn: CustomSpinner
1818
private var isTitleAscending = true
19+
private lateinit var adapter: AdapterSurvey
20+
1921
override fun getLayout(): Int {
2022
return R.layout.fragment_survey
2123
}
2224

25+
override fun onCreate(savedInstanceState: Bundle?) {
26+
super.onCreate(savedInstanceState)
27+
adapter = AdapterSurvey(requireActivity(), mRealm, model?.id ?: "")
28+
}
29+
2330
override fun getAdapter(): RecyclerView.Adapter<*> {
24-
return model?.id?.let {
25-
AdapterSurvey(requireActivity(), safeCastList(getList(RealmStepExam::class.java, "name", Sort.ASCENDING), RealmStepExam::class.java), mRealm, it)
26-
}!!
31+
return adapter
2732
}
2833

2934
@SuppressLint("ResourceAsColor")
3035
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
3136
super.onViewCreated(view, savedInstanceState)
32-
spn = requireView().findViewById(R.id.spn_sort)
33-
addNewSurvey = requireView().findViewById(R.id.fab_add_new_survey)
34-
addNewSurvey.setOnClickListener { }
35-
if (getAdapter().itemCount == 0) {
36-
spn.visibility = View.GONE
37-
}
38-
showNoData(tvMessage, getAdapter().itemCount, "survey")
37+
38+
initializeViews(view)
39+
setupRecyclerView()
40+
setupListeners()
41+
updateAdapterData()
42+
}
43+
44+
private fun initializeViews(view: View) {
45+
spn = view.findViewById(R.id.spn_sort)
46+
addNewSurvey = view.findViewById(R.id.fab_add_new_survey)
47+
}
48+
49+
private fun setupRecyclerView() {
50+
recyclerView.setHasFixedSize(true)
51+
recyclerView.adapter = adapter
52+
}
53+
54+
private fun setupListeners() {
55+
addNewSurvey.setOnClickListener {}
56+
3957
spn.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
4058
override fun onItemSelected(adapterView: AdapterView<*>?, view: View?, i: Int, l: Long) {
41-
if (view != null) {
42-
if (i == 0) {
43-
recyclerView.adapter = activity?.let { act -> model?.id?.let { id -> AdapterSurvey(act, safeCastList(getList(RealmStepExam::class.java, "createdDate", Sort.ASCENDING), RealmStepExam::class.java), mRealm, id) } }
44-
} else if (i == 1){
45-
recyclerView.adapter = activity?.let { act -> model?.id?.let { id -> AdapterSurvey(act, safeCastList(getList(RealmStepExam::class.java, "createdDate", Sort.DESCENDING), RealmStepExam::class.java), mRealm, id) } }
46-
} else {
47-
toggleTitleSortOrder()
48-
}
59+
when (i) {
60+
0 -> updateAdapterData(Sort.ASCENDING, "createdDate")
61+
1 -> updateAdapterData(Sort.DESCENDING, "createdDate")
62+
2 -> toggleTitleSortOrder()
4963
}
5064
}
5165

@@ -63,13 +77,36 @@ class SurveyFragment : BaseRecyclerFragment<RealmStepExam?>() {
6377
})
6478
}
6579

66-
fun <T> safeCastList(items: List<Any?>, clazz: Class<T>): List<T> {
67-
return items.mapNotNull { it?.takeIf(clazz::isInstance)?.let(clazz::cast) }
80+
private fun updateAdapterData(sort: Sort = Sort.ASCENDING, field: String = "name") {
81+
val newList = getList(RealmStepExam::class.java, field, sort)
82+
adapter.updateData(safeCastList(newList, RealmStepExam::class.java))
83+
updateUIState()
84+
}
85+
86+
private fun updateUIState() {
87+
val itemCount = adapter.itemCount
88+
spn.visibility = if (itemCount == 0) View.GONE else View.VISIBLE
89+
showNoData(tvMessage, itemCount, "survey")
6890
}
6991

7092
fun toggleTitleSortOrder() {
7193
isTitleAscending = !isTitleAscending
7294
val sort = if (isTitleAscending) Sort.ASCENDING else Sort.DESCENDING
73-
recyclerView.adapter = AdapterSurvey(requireActivity(), safeCastList(getList(RealmStepExam::class.java, "name", sort), RealmStepExam::class.java), mRealm, model?.id!!)
95+
updateAdapterData(sort, "name")
96+
}
97+
98+
private fun <T> safeCastList(items: List<Any?>, clazz: Class<T>): List<T> {
99+
return items.mapNotNull { it?.takeIf(clazz::isInstance)?.let(clazz::cast) }
100+
}
101+
102+
override fun onDestroy() {
103+
super.onDestroy()
104+
mRealm.close()
105+
}
106+
107+
companion object {
108+
fun newInstance(): SurveyFragment {
109+
return SurveyFragment()
110+
}
74111
}
75112
}

0 commit comments

Comments
 (0)