OOM feedback

This commit is contained in:
fanchao 2024-05-27 10:29:53 +10:00
parent 31f4de22cd
commit c0128b88de
5 changed files with 47 additions and 50 deletions

View File

@ -881,7 +881,7 @@ public class ThreadDatabase extends Database {
this.cursor = cursor;
}
public int getLength() {
public int getCount() {
return cursor == null ? 0 : cursor.getCount();
}

View File

@ -25,14 +25,16 @@ class HomeAdapter(
var header: View? = null
var data: HomeViewModel.HomeData = HomeViewModel.HomeData(emptyList(), emptySet())
var data: HomeViewModel.Data = HomeViewModel.Data(emptyList(), emptySet())
set(newData) {
if (field !== newData) {
val diff = HomeDiffUtil(field, newData, context, configFactory)
val diffResult = DiffUtil.calculateDiff(diff)
field = newData
diffResult.dispatchUpdatesTo(this as ListUpdateCallback)
if (field === newData) {
return
}
val diff = HomeDiffUtil(field, newData, context, configFactory)
val diffResult = DiffUtil.calculateDiff(diff)
field = newData
diffResult.dispatchUpdatesTo(this as ListUpdateCallback)
}
fun hasHeaderView(): Boolean = header != null

View File

@ -2,15 +2,14 @@ package org.thoughtcrime.securesms.home
import android.content.Context
import androidx.recyclerview.widget.DiffUtil
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.dependencies.ConfigFactory
import org.thoughtcrime.securesms.util.getConversationUnread
class HomeDiffUtil(
private val old: HomeViewModel.HomeData,
private val new: HomeViewModel.HomeData,
private val context: Context,
private val configFactory: ConfigFactory
private val old: HomeViewModel.Data,
private val new: HomeViewModel.Data,
private val context: Context,
private val configFactory: ConfigFactory
): DiffUtil.Callback() {
override fun getOldListSize(): Int = old.threads.size

View File

@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@ -30,8 +31,8 @@ import dagger.hilt.android.qualifiers.ApplicationContext as ApplicationContextQu
@HiltViewModel
class HomeViewModel @Inject constructor(
private val threadDb: ThreadDatabase,
contentResolver: ContentResolver,
@ApplicationContextQualifier context: Context,
private val contentResolver: ContentResolver,
@ApplicationContextQualifier private val context: Context,
) : ViewModel() {
// SharedFlow that emits whenever the user asks us to reload the conversation
private val manualReloadTrigger = MutableSharedFlow<Unit>(
@ -45,45 +46,40 @@ class HomeViewModel @Inject constructor(
* This flow will emit whenever the user asks us to reload the conversation list or
* whenever the conversation list changes.
*/
@Suppress("OPT_IN_USAGE")
val threads: StateFlow<HomeData?> =
combine(
// The conversation list data
merge(
manualReloadTrigger,
contentResolver.observeChanges(DatabaseContentProviders.ConversationList.CONTENT_URI))
.debounce(CHANGE_NOTIFICATION_DEBOUNCE_MILLS)
.onStart { emit(Unit) }
.mapLatest { _ ->
withContext(Dispatchers.IO) {
threadDb.approvedConversationList.use { openCursor ->
val reader = threadDb.readerFor(openCursor)
buildList(reader.length) {
while (true) {
add(reader.next ?: break)
}
}
}
}
},
// The typing status of each thread
ApplicationContext.getInstance(context).typingStatusRepository
.typingThreads
.asFlow()
.onStart { emit(emptySet()) }
.distinctUntilChanged(),
// The final result that we emit to the UI
::HomeData
)
val threads: StateFlow<Data?> = combine(observeConversationList(), observeTypingStatus(), ::Data)
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
private fun observeTypingStatus(): Flow<Set<Long>> =
ApplicationContext.getInstance(context).typingStatusRepository
.typingThreads
.asFlow()
.onStart { emit(emptySet()) }
.distinctUntilChanged()
@Suppress("OPT_IN_USAGE")
private fun observeConversationList(): Flow<List<ThreadRecord>> = merge(
manualReloadTrigger,
contentResolver.observeChanges(DatabaseContentProviders.ConversationList.CONTENT_URI))
.debounce(CHANGE_NOTIFICATION_DEBOUNCE_MILLS)
.onStart { emit(Unit) }
.mapLatest { _ ->
withContext(Dispatchers.IO) {
threadDb.approvedConversationList.use { openCursor ->
val reader = threadDb.readerFor(openCursor)
buildList(reader.count) {
while (true) {
add(reader.next ?: break)
}
}
}
}
}
fun tryReload() = manualReloadTrigger.tryEmit(Unit)
data class HomeData(
val threads: List<ThreadRecord>,
val typingThreadIDs: Set<Long>
data class Data(
val threads: List<ThreadRecord>,
val typingThreadIDs: Set<Long>
)
companion object {

View File

@ -11,7 +11,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
/**
* Observe changes to a content URI. This function will emit the URI whenever the content or
* Observe changes to a content Uri. This function will emit the Uri whenever the content or
* its descendants change, according to the parameter [notifyForDescendants].
*/
@CheckResult