Skip to content

Commit 57d2117

Browse files
authored
Merge branch 'master' into fix-anr-watchdog-oom
2 parents dfb1d20 + 83a17ba commit 57d2117

File tree

19 files changed

+260
-142
lines changed

19 files changed

+260
-142
lines changed

app/src/main/java/org/ole/planet/myplanet/MainApplication.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,15 @@ class MainApplication : Application(), Application.ActivityLifecycleCallbacks {
223223
}
224224

225225
private fun setupStrictMode() {
226+
if (BuildConfig.DEBUG) {
227+
val threadPolicy = StrictMode.ThreadPolicy.Builder()
228+
.detectDiskReads()
229+
.detectDiskWrites()
230+
.detectNetwork()
231+
.penaltyLog()
232+
.build()
233+
StrictMode.setThreadPolicy(threadPolicy)
234+
}
226235
val builder = VmPolicy.Builder()
227236
StrictMode.setVmPolicy(builder.build())
228237
builder.detectFileUriExposure()

app/src/main/java/org/ole/planet/myplanet/repository/NewsRepositoryImpl.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import io.realm.Sort
77
import java.util.HashMap
88
import javax.inject.Inject
99
import org.ole.planet.myplanet.datamanager.DatabaseService
10+
import org.ole.planet.myplanet.datamanager.findCopyByField
1011
import org.ole.planet.myplanet.model.RealmNews
1112
import org.ole.planet.myplanet.model.RealmNews.Companion.createNews
1213
import org.ole.planet.myplanet.model.RealmUserModel
@@ -17,12 +18,15 @@ class NewsRepositoryImpl @Inject constructor(
1718
) : RealmRepository(databaseService), NewsRepository {
1819

1920
override suspend fun getNewsWithReplies(newsId: String): Pair<RealmNews?, List<RealmNews>> {
20-
val news = findByField(RealmNews::class.java, "id", newsId)
21-
val replies = queryList(RealmNews::class.java) {
22-
equalTo("replyTo", newsId, Case.INSENSITIVE)
23-
sort("time", Sort.DESCENDING)
21+
return withRealm(ensureLatest = true) { realm ->
22+
val news = realm.findCopyByField(RealmNews::class.java, "id", newsId)
23+
val replies = realm.where(RealmNews::class.java)
24+
.equalTo("replyTo", newsId, Case.INSENSITIVE)
25+
.sort("time", Sort.DESCENDING)
26+
.findAll()
27+
.let { realm.copyFromRealm(it) }
28+
news to replies
2429
}
25-
return news to replies
2630
}
2731

2832
override suspend fun getCommunityVisibleNews(userIdentifier: String): List<RealmNews> {

app/src/main/java/org/ole/planet/myplanet/repository/RealmRepository.kt

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,28 @@ open class RealmRepository(private val databaseService: DatabaseService) {
1818
protected suspend fun <T : RealmObject> queryList(
1919
clazz: Class<T>,
2020
builder: RealmQuery<T>.() -> Unit = {},
21+
): List<T> = queryList(clazz, false, builder)
22+
23+
protected suspend fun <T : RealmObject> queryList(
24+
clazz: Class<T>,
25+
ensureLatest: Boolean,
26+
builder: RealmQuery<T>.() -> Unit = {},
2127
): List<T> =
22-
databaseService.withRealmAsync { realm ->
28+
withRealm(ensureLatest) { realm ->
2329
realm.queryList(clazz, builder)
2430
}
2531

2632
protected suspend fun <T : RealmObject> count(
2733
clazz: Class<T>,
2834
builder: RealmQuery<T>.() -> Unit = {},
35+
): Long = count(clazz, false, builder)
36+
37+
protected suspend fun <T : RealmObject> count(
38+
clazz: Class<T>,
39+
ensureLatest: Boolean,
40+
builder: RealmQuery<T>.() -> Unit = {},
2941
): Long =
30-
databaseService.withRealmAsync { realm ->
42+
withRealm(ensureLatest) { realm ->
3143
realm.where(clazz).apply(builder).count()
3244
}
3345

@@ -54,8 +66,15 @@ open class RealmRepository(private val databaseService: DatabaseService) {
5466
clazz: Class<T>,
5567
fieldName: String,
5668
value: V,
69+
): T? = findByField(clazz, fieldName, value, false)
70+
71+
protected suspend fun <T : RealmObject, V : Any> findByField(
72+
clazz: Class<T>,
73+
fieldName: String,
74+
value: V,
75+
ensureLatest: Boolean,
5776
): T? =
58-
databaseService.withRealmAsync { realm ->
77+
withRealm(ensureLatest) { realm ->
5978
realm.findCopyByField(clazz, fieldName, value)
6079
}
6180

@@ -90,8 +109,20 @@ open class RealmRepository(private val databaseService: DatabaseService) {
90109
}
91110
}
92111

112+
protected suspend fun <T> withRealm(
113+
ensureLatest: Boolean = false,
114+
operation: (Realm) -> T,
115+
): T {
116+
return databaseService.withRealmAsync { realm ->
117+
if (ensureLatest) {
118+
realm.refresh()
119+
}
120+
operation(realm)
121+
}
122+
}
123+
93124
protected suspend fun <T> withRealmAsync(operation: (Realm) -> T): T {
94-
return databaseService.withRealmAsync(operation)
125+
return withRealm(false, operation)
95126
}
96127

97128
protected fun <T> withRealmFlow(

app/src/main/java/org/ole/planet/myplanet/repository/SurveyRepositoryImpl.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package org.ole.planet.myplanet.repository
22

33
import android.content.Context
44
import dagger.hilt.android.qualifiers.ApplicationContext
5-
import io.realm.Sort
65
import javax.inject.Inject
76
import org.json.JSONException
87
import org.json.JSONObject

app/src/main/java/org/ole/planet/myplanet/service/UserProfileDbHandler.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ package org.ole.planet.myplanet.service
33
import android.content.Context
44
import android.content.SharedPreferences
55
import dagger.hilt.android.qualifiers.ApplicationContext
6-
import io.realm.Realm
7-
import kotlinx.coroutines.Dispatchers
8-
import kotlinx.coroutines.GlobalScope
9-
import kotlinx.coroutines.launch
10-
import kotlinx.coroutines.withContext
116
import java.text.SimpleDateFormat
127
import java.util.Date
138
import java.util.Locale
149
import java.util.UUID
1510
import javax.inject.Inject
11+
import kotlinx.coroutines.Dispatchers
12+
import kotlinx.coroutines.GlobalScope
13+
import kotlinx.coroutines.launch
14+
import kotlinx.coroutines.withContext
1615
import org.ole.planet.myplanet.datamanager.DatabaseService
1716
import org.ole.planet.myplanet.di.AppPreferences
1817
import org.ole.planet.myplanet.model.RealmMyLibrary

app/src/main/java/org/ole/planet/myplanet/ui/courses/AdapterCourses.kt

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class AdapterCourses(
6161

6262
companion object {
6363
private const val TAG_PAYLOAD = "payload_tags"
64+
private const val RATING_PAYLOAD = "payload_rating"
65+
private const val PROGRESS_PAYLOAD = "payload_progress"
6466
}
6567

6668
init {
@@ -84,13 +86,28 @@ class AdapterCourses(
8486
newList,
8587
areItemsTheSame = { old, new -> old?.id == new?.id },
8688
areContentsTheSame = { old, new ->
89+
val ratingSame = map[old?.courseId] == map[new?.courseId]
90+
val progressSame = progressMap?.get(old?.courseId) == progressMap?.get(new?.courseId)
91+
8792
old?.courseTitle == new?.courseTitle &&
8893
old?.description == new?.description &&
8994
old?.gradeLevel == new?.gradeLevel &&
9095
old?.subjectLevel == new?.subjectLevel &&
9196
old?.createdDate == new?.createdDate &&
9297
old?.isMyCourse == new?.isMyCourse &&
93-
old?.getNumberOfSteps() == new?.getNumberOfSteps()
98+
old?.getNumberOfSteps() == new?.getNumberOfSteps() &&
99+
ratingSame &&
100+
progressSame
101+
},
102+
getChangePayload = { old, new ->
103+
val bundle = Bundle()
104+
if (map[old?.courseId] != map[new?.courseId]) {
105+
bundle.putBoolean(RATING_PAYLOAD, true)
106+
}
107+
if (progressMap?.get(old?.courseId) != progressMap?.get(new?.courseId)) {
108+
bundle.putBoolean(PROGRESS_PAYLOAD, true)
109+
}
110+
if (bundle.isEmpty) null else bundle
94111
}
95112
)
96113
courseList = newList
@@ -176,7 +193,8 @@ class AdapterCourses(
176193
if (!isGuest) setupRatingBar(holder, course)
177194
setupCheckbox(holder, course, position, isGuest)
178195

179-
showProgressAndRating(position, holder)
196+
updateRatingViews(holder, position)
197+
updateProgressViews(holder, position)
180198

181199
holder.rowCourseBinding.root.setOnClickListener {
182200
val newPosition = holder.bindingAdapterPosition
@@ -313,10 +331,28 @@ class AdapterCourses(
313331
position: Int,
314332
payloads: MutableList<Any>
315333
) {
316-
if (holder is ViewHoldercourse && payloads.any { it == TAG_PAYLOAD }) {
317-
val courseId = courseList.getOrNull(position)?.id ?: return
318-
val tags = tagCache[courseId].orEmpty()
319-
renderTagCloud(holder.rowCourseBinding.flexboxDrawable, tags)
334+
if (holder !is ViewHoldercourse) {
335+
super.onBindViewHolder(holder, position, payloads)
336+
return
337+
}
338+
339+
val hasTagPayload = payloads.any { it == TAG_PAYLOAD }
340+
val bundle = payloads.filterIsInstance<Bundle>().fold(Bundle()) { acc, b -> acc.apply { putAll(b) } }
341+
val hasRatingPayload = bundle.containsKey(RATING_PAYLOAD)
342+
val hasProgressPayload = bundle.containsKey(PROGRESS_PAYLOAD)
343+
344+
if (hasTagPayload || hasRatingPayload || hasProgressPayload) {
345+
if (hasTagPayload) {
346+
val courseId = courseList.getOrNull(position)?.id ?: return
347+
val tags = tagCache[courseId].orEmpty()
348+
renderTagCloud(holder.rowCourseBinding.flexboxDrawable, tags)
349+
}
350+
if (hasRatingPayload) {
351+
updateRatingViews(holder, position)
352+
}
353+
if (hasProgressPayload) {
354+
updateProgressViews(holder, position)
355+
}
320356
} else {
321357
super.onBindViewHolder(holder, position, payloads)
322358
}
@@ -374,34 +410,37 @@ class AdapterCourses(
374410
}
375411
}
376412

377-
private fun showProgressAndRating(position: Int, holder: RecyclerView.ViewHolder) {
378-
val viewHolder = holder as ViewHoldercourse
379-
showProgress(viewHolder.rowCourseBinding, position)
380-
if (map.containsKey(courseList[position]!!.courseId)) {
381-
val `object` = map[courseList[position]!!.courseId]
413+
private fun updateRatingViews(holder: ViewHoldercourse, position: Int) {
414+
val course = courseList.getOrNull(position) ?: return
415+
if (map.containsKey(course.courseId)) {
416+
val ratingObject = map[course.courseId]
382417
CourseRatingUtils.showRating(
383418
context,
384-
`object`,
385-
viewHolder.rowCourseBinding.rating,
386-
viewHolder.rowCourseBinding.timesRated,
387-
viewHolder.rowCourseBinding.ratingBar
419+
ratingObject,
420+
holder.rowCourseBinding.rating,
421+
holder.rowCourseBinding.timesRated,
422+
holder.rowCourseBinding.ratingBar
388423
)
389424
} else {
390-
viewHolder.rowCourseBinding.ratingBar.rating = 0f
425+
holder.rowCourseBinding.ratingBar.rating = 0f
426+
holder.rowCourseBinding.rating.text = context.getString(R.string.zero_point_zero)
427+
holder.rowCourseBinding.timesRated.text = context.getString(R.string.rating_count_format, 0)
391428
}
392429
}
393430

394-
private fun showProgress(binding: RowCourseBinding, position: Int) {
395-
if (progressMap?.containsKey(courseList[position]?.courseId) == true) {
396-
val ob = progressMap!![courseList[position]?.courseId]
397-
binding.courseProgress.max = getInt("max", ob)
398-
binding.courseProgress.progress = getInt("current", ob)
399-
if (getInt("current", ob) < getInt("max", ob)) {
400-
binding.courseProgress.secondaryProgress = getInt("current", ob) + 1
431+
private fun updateProgressViews(holder: ViewHoldercourse, position: Int) {
432+
val course = courseList.getOrNull(position) ?: return
433+
val progress = progressMap?.get(course.courseId)
434+
if (progress != null) {
435+
holder.rowCourseBinding.courseProgress.max = getInt("max", progress)
436+
val currentProgress = getInt("current", progress)
437+
holder.rowCourseBinding.courseProgress.progress = currentProgress
438+
if (currentProgress < holder.rowCourseBinding.courseProgress.max) {
439+
holder.rowCourseBinding.courseProgress.secondaryProgress = currentProgress + 1
401440
}
402-
binding.courseProgress.visibility = View.VISIBLE
441+
holder.rowCourseBinding.courseProgress.visibility = View.VISIBLE
403442
} else {
404-
binding.courseProgress.visibility = View.GONE
443+
holder.rowCourseBinding.courseProgress.visibility = View.GONE
405444
}
406445
}
407446

app/src/main/java/org/ole/planet/myplanet/ui/courses/CourseStepFragment.kt

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import androidx.fragment.app.Fragment
1111
import androidx.lifecycle.lifecycleScope
1212
import java.util.Date
1313
import java.util.UUID
14+
import kotlinx.coroutines.Job
1415
import kotlinx.coroutines.launch
1516
import org.ole.planet.myplanet.MainApplication
1617
import org.ole.planet.myplanet.R
@@ -39,6 +40,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback {
3940
private lateinit var stepSurvey: List<RealmStepExam>
4041
var user: RealmUserModel? = null
4142
private var stepNumber = 0
43+
private var saveInProgress: Job? = null
4244
override fun onCreate(savedInstanceState: Bundle?) {
4345
super.onCreate(savedInstanceState)
4446
if (arguments != null) {
@@ -55,12 +57,11 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback {
5557
return fragmentCourseStepBinding.root
5658
}
5759

58-
private fun saveCourseProgress() {
59-
databaseService.withRealm { realm ->
60-
if (!realm.isInTransaction) realm.beginTransaction()
60+
private suspend fun saveCourseProgress(userId: String?, planetCode: String?, parentCode: String?) {
61+
databaseService.executeTransactionAsync { realm ->
6162
var courseProgress = realm.where(RealmCourseProgress::class.java)
6263
.equalTo("courseId", step.courseId)
63-
.equalTo("userId", user?.id)
64+
.equalTo("userId", userId)
6465
.equalTo("stepNum", stepNumber)
6566
.findFirst()
6667
if (courseProgress == null) {
@@ -72,12 +73,22 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback {
7273
if (stepExams.isEmpty()) {
7374
courseProgress?.passed = true
7475
}
75-
courseProgress?.createdOn = user?.planetCode
76+
courseProgress?.createdOn = planetCode
7677
courseProgress?.updatedDate = Date().time
77-
courseProgress?.parentCode = user?.parentCode
78-
courseProgress?.userId = user?.id
79-
realm.commitTransaction()
78+
courseProgress?.parentCode = parentCode
79+
courseProgress?.userId = userId
80+
}
81+
}
82+
83+
private fun launchSaveCourseProgress() {
84+
if (saveInProgress?.isActive == true) return
85+
val userId = user?.id
86+
val planetCode = user?.planetCode
87+
val parentCode = user?.parentCode
88+
saveInProgress = lifecycleScope.launch {
89+
saveCourseProgress(userId, planetCode, parentCode)
8090
}
91+
saveInProgress?.invokeOnCompletion { saveInProgress = null }
8192
}
8293
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
8394
super.onViewCreated(view, savedInstanceState)
@@ -132,7 +143,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback {
132143
}
133144
}
134145
if (isVisible && userHasCourse) {
135-
saveCourseProgress()
146+
launchSaveCourseProgress()
136147
}
137148
}
138149

@@ -171,7 +182,7 @@ class CourseStepFragment : BaseContainerFragment(), ImageCaptureCallback {
171182
isMyCourse(user?.id, step.courseId, realm)
172183
}
173184
if (userHasCourse) {
174-
saveCourseProgress()
185+
launchSaveCourseProgress()
175186
}
176187
}
177188
} catch (e: Exception) {

app/src/main/java/org/ole/planet/myplanet/ui/courses/TakeCourseFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ class TakeCourseFragment : Fragment(), ViewPager.OnPageChangeListener, View.OnCl
191191
}
192192
}
193193

194-
val detachedUserModel = userModel?.let { mRealm.copyFromRealm(it) }
194+
val detachedUserModel = userModel
195195
val detachedCurrentCourse = currentCourse?.let { mRealm.copyFromRealm(it) }
196196

197197
withContext(Dispatchers.IO) {

app/src/main/java/org/ole/planet/myplanet/ui/dashboard/BaseDashboardFragment.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import androidx.lifecycle.lifecycleScope
1717
import com.bumptech.glide.Glide
1818
import com.google.android.flexbox.FlexDirection
1919
import com.google.android.flexbox.FlexboxLayout
20-
import io.realm.Realm
2120
import io.realm.Case
21+
import io.realm.Realm
2222
import io.realm.RealmChangeListener
2323
import io.realm.RealmObject
2424
import io.realm.RealmResults

0 commit comments

Comments
 (0)