Fix PrivateMessageDataSource making way to many requests

This commit is contained in:
Balazs Toldi 2023-08-18 13:18:21 +02:00
parent 3e17e3364d
commit bae68d4a99
No known key found for this signature in database
GPG Key ID: 6C7D440036F99D58
4 changed files with 65 additions and 158 deletions

View File

@ -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); mLinearLayoutManager = new LinearLayoutManagerBugFixed(mActivity);
mRecyclerView.setLayoutManager(mLinearLayoutManager); mRecyclerView.setLayoutManager(mLinearLayoutManager);
mRecyclerView.setAdapter(mAdapter); mRecyclerView.setAdapter(mAdapter);
@ -133,19 +133,10 @@ public class PrivateMessageFragment extends Fragment implements FragmentCommunic
PrivateMessageViewModel.Factory factory = new PrivateMessageViewModel.Factory(mRetrofit.getRetrofit(), PrivateMessageViewModel.Factory factory = new PrivateMessageViewModel.Factory(mRetrofit.getRetrofit(),
getResources().getConfiguration().locale, mAccessToken, mLemmyPrivateMessageAPI); getResources().getConfiguration().locale, mAccessToken, mLemmyPrivateMessageAPI);
mMessageViewModel = new ViewModelProvider(this, factory).get(PrivateMessageViewModel.class); 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)) { if (networkState.getStatus().equals(NetworkState.Status.SUCCESS)) {
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
} else if (networkState.getStatus().equals(NetworkState.Status.FAILED)) { } 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); mSwipeRefreshLayout.setOnRefreshListener(this::onRefresh);
@ -216,14 +204,14 @@ public class PrivateMessageFragment extends Fragment implements FragmentCommunic
private void onRefresh() { private void onRefresh() {
mMessageViewModel.refresh(); mMessageViewModel.refresh();
mAdapter.setNetworkState(null); mSwipeRefreshLayout.setRefreshing(false);
} }
public PrivateMessage getMessageByIndex(int index) { public PrivateMessage getMessageByIndex(int index) {
if (mMessageViewModel == null || index < 0) { if (mMessageViewModel == null || index < 0) {
return null; return null;
} }
PagedList<PrivateMessage> messages = mMessageViewModel.getMessages().getValue(); PagedList<PrivateMessage> messages = mMessageViewModel.getPrivateMessages().getValue();
if (messages == null) { if (messages == null) {
return null; return null;
} }

View File

@ -3,61 +3,62 @@ package eu.toldi.infinityforlemmy.privatemessage
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.paging.PageKeyedDataSource import androidx.paging.PageKeyedDataSource
import eu.toldi.infinityforlemmy.NetworkState import eu.toldi.infinityforlemmy.NetworkState
import retrofit2.Retrofit
import java.util.Locale
class PrivateMessageDataSource( class PrivateMessageDataSource(
private val retrofit: Retrofit, private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI,
private val locale: Locale, private val accessToken: String
private val accessToken: String, ) : PageKeyedDataSource<Int, PrivateMessage>() {
private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI
) :
PageKeyedDataSource<Int, PrivateMessage>() {
val initialLoadStateLiveData = MutableLiveData<NetworkState>()
val paginationNetworkStateLiveData: MutableLiveData<NetworkState> = MutableLiveData()
val initialLoadStateLiveData: MutableLiveData<NetworkState>
private val hasPostLiveData: MutableLiveData<Boolean>
private var params: LoadParams<Int>? = null
private var callback: LoadCallback<Int, PrivateMessage>? = null
private val page = 1
init {
initialLoadStateLiveData = MutableLiveData()
hasPostLiveData = MutableLiveData()
}
fun hasPostLiveData(): MutableLiveData<Boolean> {
return hasPostLiveData
}
fun retryLoadingMore() {
loadAfter(params!!, callback!!)
}
override fun loadInitial( override fun loadInitial(
params: LoadInitialParams<Int>, params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, PrivateMessage> callback: LoadInitialCallback<Int, PrivateMessage>
) { ) {
initialLoadStateLiveData.postValue(NetworkState.LOADING) mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, 1, object :
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, page, object :
LemmyPrivateMessageAPI.PrivateMessageFetchedListener { LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) { override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
hasPostLiveData.postValue(true) initialLoadStateLiveData.postValue(NetworkState.LOADED)
if (privateMessages.isEmpty()) { if (privateMessages.isEmpty()) {
callback.onResult(ArrayList(), null, null) callback.onResult(ArrayList(), null, null)
} else { } else {
callback.onResult(privateMessages, null, 2) callback.onResult(privateMessages, null, 2)
} }
initialLoadStateLiveData.postValue(NetworkState.LOADED)
} }
override fun onPrivateMessageFetchedError() { override fun onPrivateMessageFetchedError() {
initialLoadStateLiveData.postValue( initialLoadStateLiveData.postValue(
NetworkState( NetworkState(
NetworkState.Status.FAILED, NetworkState.Status.FAILED,
"Error fetch messages" "Error fetching messages"
)
)
}
})
}
override fun loadAfter(
params: LoadParams<Int>,
callback: LoadCallback<Int, PrivateMessage>
) {
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, params.key, object :
LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
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<Int>, params: LoadParams<Int>,
callback: LoadCallback<Int, PrivateMessage> callback: LoadCallback<Int, PrivateMessage>
) { ) {
} }
override fun loadAfter( fun refresh() {
params: LoadParams<Int>, invalidate()
callback: LoadCallback<Int, PrivateMessage>
) {
this.params = params
this.callback = callback
paginationNetworkStateLiveData.postValue(NetworkState.LOADING)
mLemmyPrivateMessageAPI.fetchPrivateMessages(accessToken, params.key, object :
LemmyPrivateMessageAPI.PrivateMessageFetchedListener {
override fun onPrivateMessageFetchedSuccess(privateMessages: List<PrivateMessage>) {
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"
)
)
}
})
} }
} }

View File

@ -2,36 +2,19 @@ package eu.toldi.infinityforlemmy.privatemessage
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.paging.DataSource import androidx.paging.DataSource
import retrofit2.Retrofit
import java.util.Locale
internal class PrivateMessageDataSourceFactory( class PrivateMessageDataSourceFactory(
retrofit: Retrofit, private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI,
locale: Locale, private val accessToken: String
accessToken: String,
private var mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI
) : DataSource.Factory<Int, PrivateMessage>() { ) : DataSource.Factory<Int, PrivateMessage>() {
private val mPrivateMessageDataSource: PrivateMessageDataSource =
PrivateMessageDataSource(retrofit, locale, accessToken, mLemmyPrivateMessageAPI) val dataSourceLiveData = MutableLiveData<PrivateMessageDataSource>()
private val messageDataSourceLiveData: MutableLiveData<PrivateMessageDataSource> =
MutableLiveData<PrivateMessageDataSource>()
override fun create(): DataSource<Int, PrivateMessage> { override fun create(): DataSource<Int, PrivateMessage> {
messageDataSourceLiveData.postValue(mPrivateMessageDataSource) val dataSource = PrivateMessageDataSource(mLemmyPrivateMessageAPI, accessToken)
return mPrivateMessageDataSource dataSourceLiveData.postValue(dataSource)
return dataSource
} }
fun getMessageDataSourceLiveData(): MutableLiveData<PrivateMessageDataSource> {
return messageDataSourceLiveData
}
fun getMessageDataSource(): PrivateMessageDataSource {
return mPrivateMessageDataSource
}
fun changeLemmPrivateMessageAPI(lemmyPrivateMessageAPI: LemmyPrivateMessageAPI) {
this.mLemmyPrivateMessageAPI = lemmyPrivateMessageAPI
}
} }

View File

@ -1,76 +1,38 @@
package eu.toldi.infinityforlemmy.privatemessage package eu.toldi.infinityforlemmy.privatemessage
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations import androidx.lifecycle.Transformations
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.paging.LivePagedListBuilder import androidx.paging.LivePagedListBuilder
import androidx.paging.PagedList import androidx.paging.PagedList
import eu.toldi.infinityforlemmy.NetworkState
import retrofit2.Retrofit import retrofit2.Retrofit
import java.util.Locale import java.util.Locale
class PrivateMessageViewModel( class PrivateMessageViewModel(
retrofit: Retrofit, private val mLemmyPrivateMessageAPI: LemmyPrivateMessageAPI,
locale: Locale, private val accessToken: String
accessToken: String, ) : ViewModel() {
lemmyPrivateMessageAPI: LemmyPrivateMessageAPI
) :
ViewModel() {
private val messageDataSourceFactory: PrivateMessageDataSourceFactory
val paginationNetworkState: LiveData<NetworkState>
val initialLoadingState: LiveData<NetworkState>
private val hasMessageLiveData: LiveData<Boolean>
val messages: LiveData<PagedList<PrivateMessage>>
private val whereLiveData: MutableLiveData<LemmyPrivateMessageAPI> = MutableLiveData()
init { private val dataSourceFactory =
messageDataSourceFactory = PrivateMessageDataSourceFactory(mLemmyPrivateMessageAPI, accessToken)
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
)
whereLiveData.postValue(lemmyPrivateMessageAPI) val privateMessages = LivePagedListBuilder(
dataSourceFactory, PagedList.Config.Builder()
val pagedListConfig: PagedList.Config = PagedList.Config.Builder() .setPageSize(20)
.setEnablePlaceholders(false) .setEnablePlaceholders(false)
.setPageSize(25)
.build() .build()
messages = Transformations.switchMap<LemmyPrivateMessageAPI, PagedList<PrivateMessage>>( )
whereLiveData .build()
) { newWhere: LemmyPrivateMessageAPI? ->
messageDataSourceFactory.changeLemmPrivateMessageAPI(whereLiveData.value!!)
LivePagedListBuilder(
messageDataSourceFactory,
pagedListConfig
).build()
}
} val initialLoadState = Transformations.switchMap(dataSourceFactory.dataSourceLiveData) {
it.initialLoadStateLiveData
fun hasMessage(): LiveData<Boolean> {
return hasMessageLiveData
} }
fun refresh() { fun refresh() {
messageDataSourceFactory.getMessageDataSource().invalidate() dataSourceFactory.dataSourceLiveData.value?.refresh()
} }
fun retryLoadingMore() {
messageDataSourceFactory.getMessageDataSource().retryLoadingMore()
}
class Factory( class Factory(
private val retrofit: Retrofit, private val retrofit: Retrofit,
@ -82,10 +44,8 @@ class PrivateMessageViewModel(
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
return PrivateMessageViewModel( return PrivateMessageViewModel(
retrofit, lemmyPrivateMessageAPI,
locale,
accessToken, accessToken,
lemmyPrivateMessageAPI
) as T ) as T
} }
} }