New Observer/Observable performance improvements.

This commit is contained in:
Vitor Pamplona 2023-01-18 15:30:39 -05:00
parent bf8a0f0e76
commit 9792733f72
11 changed files with 99 additions and 13 deletions

View File

@ -8,7 +8,7 @@ import nostr.postr.events.TextNoteEvent
object NostrGlobalDataSource: NostrDataSource<Note>("GlobalFeed") {
fun createGlobalFilter() = JsonFilter(
kinds = listOf(TextNoteEvent.kind),
limit = 200
limit = 50
)
val globalFeedChannel = requestNewChannel()

View File

@ -1,7 +1,6 @@
package com.vitorpamplona.amethyst.service.relays
import com.google.gson.JsonElement
import java.util.Collections
import nostr.postr.events.Event
import okhttp3.OkHttpClient
import okhttp3.Request

View File

@ -1,5 +1,7 @@
package com.vitorpamplona.amethyst.ui.screen
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.LocalCache
@ -89,8 +91,21 @@ class CardFeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
}
}
val filterHandler = Handler(Looper.getMainLooper())
var handlerWaiting = false
@Synchronized
fun invalidateData() {
if (handlerWaiting) return
handlerWaiting = true
filterHandler.postDelayed({
refresh()
handlerWaiting = false
}, 100)
}
private val cacheListener: (LocalCacheState) -> Unit = {
refresh()
invalidateData()
}
init {

View File

@ -1,11 +1,15 @@
package com.vitorpamplona.amethyst.ui.screen
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.LocalCacheState
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.NostrDataSource
import kotlin.time.ExperimentalTime
import kotlin.time.measureTimedValue
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@ -20,16 +24,23 @@ class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
private val _feedContent = MutableStateFlow<FeedState>(FeedState.Loading)
val feedContent = _feedContent.asStateFlow()
@OptIn(ExperimentalTime::class)
fun refresh() {
val notes = dataSource.loadTop()
val scope = CoroutineScope(Job() + Dispatchers.Main)
scope.launch {
println("AAA" + measureTimedValue {
val notes = dataSource.loadTop()
val oldNotesState = feedContent.value
if (oldNotesState is FeedState.Loaded) {
if (notes != oldNotesState.feed) {
updateFeed(notes)
}
} else {
updateFeed(notes)
}
}.duration)
val oldNotesState = feedContent.value
if (oldNotesState is FeedState.Loaded) {
if (notes != oldNotesState.feed) {
updateFeed(notes)
}
} else {
updateFeed(notes)
}
}
@ -48,8 +59,21 @@ class FeedViewModel(val dataSource: NostrDataSource<Note>): ViewModel() {
}
}
val filterHandler = Handler(Looper.getMainLooper())
var handlerWaiting = false
@Synchronized
fun invalidateData() {
if (handlerWaiting) return
handlerWaiting = true
filterHandler.postDelayed({
refresh()
handlerWaiting = false
}, 100)
}
private val cacheListener: (LocalCacheState) -> Unit = {
refresh()
invalidateData()
}
init {

View File

@ -1,5 +1,7 @@
package com.vitorpamplona.amethyst.ui.screen
import android.os.Handler
import android.os.Looper
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.LocalCache
@ -61,8 +63,21 @@ open class UserFeedViewModel(val dataSource: NostrDataSource<User>): ViewModel()
}
}
val filterHandler = Handler(Looper.getMainLooper())
var handlerWaiting = false
@Synchronized
fun invalidateData() {
if (handlerWaiting) return
handlerWaiting = true
filterHandler.postDelayed({
refresh()
handlerWaiting = false
}, 100)
}
private val cacheListener: (LocalCacheState) -> Unit = {
refresh()
invalidateData()
}
init {

View File

@ -57,6 +57,10 @@ fun ChannelScreen(channelId: String?, accountViewModel: AccountViewModel, navCon
val feedViewModel: FeedViewModel = viewModel { FeedViewModel( NostrChannelDataSource ) }
LaunchedEffect(Unit) {
feedViewModel.refresh()
}
Column(Modifier.fillMaxHeight()) {
ChannelHeader(
channel,

View File

@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
@ -20,6 +21,10 @@ fun ChatroomListScreen(accountViewModel: AccountViewModel, navController: NavCon
if (account != null) {
val feedViewModel: FeedViewModel = viewModel { FeedViewModel( NostrChatroomListDataSource ) }
LaunchedEffect(Unit) {
feedViewModel.refresh()
}
Column(Modifier.fillMaxHeight()) {
Column(
modifier = Modifier.padding(vertical = 0.dp)

View File

@ -17,6 +17,7 @@ import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
@ -48,6 +49,10 @@ fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navContr
val feedViewModel: FeedViewModel = viewModel { FeedViewModel( NostrChatRoomDataSource ) }
LaunchedEffect(Unit) {
feedViewModel.refresh()
}
Column(Modifier.fillMaxHeight()) {
NostrChatRoomDataSource.withUser?.let {
ChatroomHeader(

View File

@ -4,6 +4,8 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
@ -12,6 +14,9 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.vitorpamplona.amethyst.service.NostrHomeDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileFollowersDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileFollowsDataSource
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import java.lang.System.currentTimeMillis
@ -22,6 +27,10 @@ fun HomeScreen(accountViewModel: AccountViewModel, navController: NavController)
if (accountState != null) {
val feedViewModel: FeedViewModel = viewModel { FeedViewModel( NostrHomeDataSource ) }
LaunchedEffect(Unit) {
feedViewModel.refresh()
}
Column(Modifier.fillMaxHeight()) {
Column(
modifier = Modifier.padding(vertical = 0.dp)

View File

@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
@ -21,6 +22,10 @@ fun NotificationScreen(accountViewModel: AccountViewModel, navController: NavCon
val feedViewModel: CardFeedViewModel =
viewModel { CardFeedViewModel( NostrNotificationDataSource ) }
LaunchedEffect(Unit) {
feedViewModel.refresh()
}
Column(Modifier.fillMaxHeight()) {
Column(
modifier = Modifier.padding(vertical = 0.dp)

View File

@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
@ -15,6 +16,10 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
fun SearchScreen(accountViewModel: AccountViewModel, navController: NavController) {
val feedViewModel: FeedViewModel = viewModel { FeedViewModel( NostrGlobalDataSource ) }
LaunchedEffect(Unit) {
feedViewModel.refresh()
}
Column(Modifier.fillMaxHeight()) {
Column(
modifier = Modifier.padding(vertical = 0.dp)