From bae68d4a9948c1e5caee17bb65206c3187d940f8 Mon Sep 17 00:00:00 2001 From: Balazs Toldi Date: Fri, 18 Aug 2023 13:18:21 +0200 Subject: [PATCH] Fix PrivateMessageDataSource making way to many requests --- .../fragments/PrivateMessageFragment.java | 22 +---- .../PrivateMessageDataSource.kt | 98 +++++++------------ .../PrivateMessageDataSourceFactory.kt | 35 ++----- .../privatemessage/PrivateMessageViewModel.kt | 68 +++---------- 4 files changed, 65 insertions(+), 158 deletions(-) diff --git a/app/src/main/java/eu/toldi/infinityforlemmy/fragments/PrivateMessageFragment.java b/app/src/main/java/eu/toldi/infinityforlemmy/fragments/PrivateMessageFragment.java index 2c9b0923..84b753de 100644 --- a/app/src/main/java/eu/toldi/infinityforlemmy/fragments/PrivateMessageFragment.java +++ b/app/src/main/java/eu/toldi/infinityforlemmy/fragments/PrivateMessageFragment.java @@ -110,7 +110,7 @@ public class PrivateMessageFragment extends Fragment implements FragmentCommunic } - mAdapter = new PrivateMessageRecycleViewAdapter(mActivity, mRetrofit.getRetrofit(), mCustomThemeWrapper, mAccessToken, mLemmyPrivateMessageAPI, () -> mMessageViewModel.retryLoadingMore()); + mAdapter = new PrivateMessageRecycleViewAdapter(mActivity, mRetrofit.getRetrofit(), mCustomThemeWrapper, mAccessToken, mLemmyPrivateMessageAPI, () -> mMessageViewModel.refresh()); mLinearLayoutManager = new LinearLayoutManagerBugFixed(mActivity); mRecyclerView.setLayoutManager(mLinearLayoutManager); mRecyclerView.setAdapter(mAdapter); @@ -133,19 +133,10 @@ public class PrivateMessageFragment extends Fragment implements FragmentCommunic PrivateMessageViewModel.Factory factory = new PrivateMessageViewModel.Factory(mRetrofit.getRetrofit(), getResources().getConfiguration().locale, mAccessToken, mLemmyPrivateMessageAPI); mMessageViewModel = new ViewModelProvider(this, factory).get(PrivateMessageViewModel.class); - mMessageViewModel.getMessages().observe(getViewLifecycleOwner(), messages -> mAdapter.submitList(messages)); + mMessageViewModel.getPrivateMessages().observe(getViewLifecycleOwner(), messages -> mAdapter.submitList(messages)); - mMessageViewModel.hasMessage().observe(getViewLifecycleOwner(), hasMessage -> { - mSwipeRefreshLayout.setRefreshing(false); - if (hasMessage) { - mFetchMessageInfoLinearLayout.setVisibility(View.GONE); - } else { - mFetchMessageInfoLinearLayout.setOnClickListener(null); - showErrorView(R.string.no_messages); - } - }); - mMessageViewModel.getInitialLoadingState().observe(getViewLifecycleOwner(), networkState -> { + mMessageViewModel.getInitialLoadState().observe(getViewLifecycleOwner(), networkState -> { if (networkState.getStatus().equals(NetworkState.Status.SUCCESS)) { mSwipeRefreshLayout.setRefreshing(false); } else if (networkState.getStatus().equals(NetworkState.Status.FAILED)) { @@ -161,9 +152,6 @@ public class PrivateMessageFragment extends Fragment implements FragmentCommunic } }); - mMessageViewModel.getPaginationNetworkState().observe(getViewLifecycleOwner(), networkState -> { - mAdapter.setNetworkState(networkState); - }); mSwipeRefreshLayout.setOnRefreshListener(this::onRefresh); @@ -216,14 +204,14 @@ public class PrivateMessageFragment extends Fragment implements FragmentCommunic private void onRefresh() { mMessageViewModel.refresh(); - mAdapter.setNetworkState(null); + mSwipeRefreshLayout.setRefreshing(false); } public PrivateMessage getMessageByIndex(int index) { if (mMessageViewModel == null || index < 0) { return null; } - PagedList messages = mMessageViewModel.getMessages().getValue(); + PagedList messages = mMessageViewModel.getPrivateMessages().getValue(); if (messages == null) { return null; } diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt index a93edba9..37f3ce1c 100644 --- a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSource.kt @@ -3,61 +3,62 @@ package eu.toldi.infinityforlemmy.privatemessage import androidx.lifecycle.MutableLiveData import androidx.paging.PageKeyedDataSource import eu.toldi.infinityforlemmy.NetworkState -import retrofit2.Retrofit -import java.util.Locale class PrivateMessageDataSource( - private val retrofit: Retrofit, - private val locale: Locale, - private val accessToken: String, - private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI -) : - PageKeyedDataSource() { + private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI, + private val accessToken: String +) : PageKeyedDataSource() { - - val paginationNetworkStateLiveData: MutableLiveData = MutableLiveData() - val initialLoadStateLiveData: MutableLiveData - private val hasPostLiveData: MutableLiveData - private var params: LoadParams? = null - private var callback: LoadCallback? = null - private val page = 1 - - init { - initialLoadStateLiveData = MutableLiveData() - hasPostLiveData = MutableLiveData() - } - - fun hasPostLiveData(): MutableLiveData { - return hasPostLiveData - } - - fun retryLoadingMore() { - loadAfter(params!!, callback!!) - } + val initialLoadStateLiveData = MutableLiveData() override fun loadInitial( params: LoadInitialParams, callback: LoadInitialCallback ) { - initialLoadStateLiveData.postValue(NetworkState.LOADING) - mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, page, object : + mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, 1, object : LemmyPrivateMessageAPI.PrivateMessageFetchedListener { override fun onPrivateMessageFetchedSuccess(privateMessages: List) { - hasPostLiveData.postValue(true) + initialLoadStateLiveData.postValue(NetworkState.LOADED) if (privateMessages.isEmpty()) { callback.onResult(ArrayList(), null, null) } else { callback.onResult(privateMessages, null, 2) } - initialLoadStateLiveData.postValue(NetworkState.LOADED) } override fun onPrivateMessageFetchedError() { initialLoadStateLiveData.postValue( NetworkState( NetworkState.Status.FAILED, - "Error fetch messages" + "Error fetching messages" + ) + ) + } + }) + } + + override fun loadAfter( + params: LoadParams, + callback: LoadCallback + ) { + mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, params.key, object : + LemmyPrivateMessageAPI.PrivateMessageFetchedListener { + override fun onPrivateMessageFetchedSuccess(privateMessages: List) { + initialLoadStateLiveData.postValue(NetworkState.LOADED) + if (privateMessages.isEmpty()) { + callback.onResult(ArrayList(), null) + } else { + callback.onResult(privateMessages, params.key + 1) + } + + } + + override fun onPrivateMessageFetchedError() { + initialLoadStateLiveData.postValue( + NetworkState( + NetworkState.Status.FAILED, + "Error fetching messages" ) ) } @@ -68,35 +69,10 @@ class PrivateMessageDataSource( params: LoadParams, callback: LoadCallback ) { + } - override fun loadAfter( - params: LoadParams, - callback: LoadCallback - ) { - this.params = params - this.callback = callback - paginationNetworkStateLiveData.postValue(NetworkState.LOADING) - mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, params.key, object : - LemmyPrivateMessageAPI.PrivateMessageFetchedListener { - override fun onPrivateMessageFetchedSuccess(privateMessages: List) { - hasPostLiveData.postValue(true) - if (privateMessages.isEmpty()) { - callback.onResult(ArrayList(), null) - } else { - callback.onResult(privateMessages, params.key + 1) - } - paginationNetworkStateLiveData.postValue(NetworkState.LOADED) - } - - override fun onPrivateMessageFetchedError() { - paginationNetworkStateLiveData.postValue( - NetworkState( - NetworkState.Status.FAILED, - "Error fetch messages" - ) - ) - } - }) + fun refresh() { + invalidate() } } diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSourceFactory.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSourceFactory.kt index baf48cbc..33631c29 100644 --- a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSourceFactory.kt +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageDataSourceFactory.kt @@ -2,36 +2,19 @@ package eu.toldi.infinityforlemmy.privatemessage import androidx.lifecycle.MutableLiveData import androidx.paging.DataSource -import retrofit2.Retrofit -import java.util.Locale -internal class PrivateMessageDataSourceFactory( - retrofit: Retrofit, - locale: Locale, - accessToken: String, - private var mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI +class PrivateMessageDataSourceFactory( + private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI, + private val accessToken: String ) : DataSource.Factory() { - private val mPrivateMessageDataSource: PrivateMessageDataSource = - PrivateMessageDataSource(retrofit, locale, accessToken, mLemmyPrivateMessageAPI) - private val messageDataSourceLiveData: MutableLiveData = - MutableLiveData() + + val dataSourceLiveData = MutableLiveData() override fun create(): DataSource { - messageDataSourceLiveData.postValue(mPrivateMessageDataSource) - return mPrivateMessageDataSource + val dataSource = PrivateMessageDataSource(mLemmyPrivateMessageAPI, accessToken) + dataSourceLiveData.postValue(dataSource) + return dataSource } - - fun getMessageDataSourceLiveData(): MutableLiveData { - return messageDataSourceLiveData - } - - fun getMessageDataSource(): PrivateMessageDataSource { - return mPrivateMessageDataSource - } - - fun changeLemmPrivateMessageAPI(lemmyPrivateMessageAPI: LemmyPrivateMessageAPI) { - this.mLemmyPrivateMessageAPI = lemmyPrivateMessageAPI - } - } + diff --git a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageViewModel.kt b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageViewModel.kt index 835178ae..5296c236 100644 --- a/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageViewModel.kt +++ b/app/src/main/kotlin/eu/toldi/infinityforlemmy/privatemessage/PrivateMessageViewModel.kt @@ -1,76 +1,38 @@ package eu.toldi.infinityforlemmy.privatemessage -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.paging.LivePagedListBuilder import androidx.paging.PagedList -import eu.toldi.infinityforlemmy.NetworkState import retrofit2.Retrofit import java.util.Locale class PrivateMessageViewModel( - retrofit: Retrofit, - locale: Locale, - accessToken: String, - lemmyPrivateMessageAPI: LemmyPrivateMessageAPI -) : - ViewModel() { - private val messageDataSourceFactory: PrivateMessageDataSourceFactory - val paginationNetworkState: LiveData - val initialLoadingState: LiveData - private val hasMessageLiveData: LiveData - val messages: LiveData> - private val whereLiveData: MutableLiveData = MutableLiveData() + private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI, + private val accessToken: String +) : ViewModel() { - init { - messageDataSourceFactory = - PrivateMessageDataSourceFactory(retrofit, locale, accessToken, lemmyPrivateMessageAPI) - initialLoadingState = Transformations.switchMap( - messageDataSourceFactory.getMessageDataSourceLiveData(), - PrivateMessageDataSource::initialLoadStateLiveData - ) - paginationNetworkState = Transformations.switchMap( - messageDataSourceFactory.getMessageDataSourceLiveData(), - PrivateMessageDataSource::paginationNetworkStateLiveData - ) - hasMessageLiveData = Transformations.switchMap( - messageDataSourceFactory.getMessageDataSourceLiveData(), - PrivateMessageDataSource::hasPostLiveData - ) + private val dataSourceFactory = + PrivateMessageDataSourceFactory(mLemmyPrivateMessageAPI, accessToken) - whereLiveData.postValue(lemmyPrivateMessageAPI) - - val pagedListConfig: PagedList.Config = PagedList.Config.Builder() + val privateMessages = LivePagedListBuilder( + dataSourceFactory, PagedList.Config.Builder() + .setPageSize(20) .setEnablePlaceholders(false) - .setPageSize(25) .build() - messages = Transformations.switchMap>( - whereLiveData - ) { newWhere: LemmyPrivateMessageAPI? -> - messageDataSourceFactory.changeLemmPrivateMessageAPI(whereLiveData.value!!) - LivePagedListBuilder( - messageDataSourceFactory, - pagedListConfig - ).build() - } + ) + .build() - } - - fun hasMessage(): LiveData { - return hasMessageLiveData + val initialLoadState = Transformations.switchMap(dataSourceFactory.dataSourceLiveData) { + it.initialLoadStateLiveData } fun refresh() { - messageDataSourceFactory.getMessageDataSource().invalidate() + dataSourceFactory.dataSourceLiveData.value?.refresh() } - fun retryLoadingMore() { - messageDataSourceFactory.getMessageDataSource().retryLoadingMore() - } class Factory( private val retrofit: Retrofit, @@ -82,10 +44,8 @@ class PrivateMessageViewModel( override fun create(modelClass: Class): T { return PrivateMessageViewModel( - retrofit, - locale, + lemmyPrivateMessageAPI, accessToken, - lemmyPrivateMessageAPI ) as T } }