Good afternoon
In the TMessagePagingSource class (extends from PagingSource<TMessageKey, TMessage>) I override the load() function:
public class TMessagePagingSource extends PagingSource<TMessageKey, TMessage> {
...
@Nullable
@Override
public Object load(@NonNull LoadParams<TMessageKey> loadParams, @NonNull Continuation<? super LoadResult<TMessageKey, TMessage>> continuation) {
TMessageKey pageKey = loadParams.getKey();
if (pageKey == null) {
pageKey = new TMessageKey(Long.MAX_VALUE, true, false);
}
int pageSize = loadParams.getLoadSize();
mBackend.getTMessagesPage(pageKey, pageSize, this, continuation);
return null;
}
public void toResult(TMessageResponse response, @NonNull Continuation<? super LoadResult<TMessageKey, TMessage>> continuation){
LoadResult<TMessageKey, TMessage> result;
try {
result = new LoadResult.Page(
response.getMessages(),
response.getPrevPageKey(),
response.getNextPageKey()
);
} catch (Exception e) {
result = new LoadResult.Error(e);
}
try {
synchronized (continuation) {
continuation.resumeWith(result);
}
} catch (Exception e) {}
}
}
The mBackend.getTMessagesPage() function does not return the result immediately. It internally calls another function asynchronously, and that function, in turn, asynchronously calls another one. As a result, one of the asynchronous nested functions returns the result (pagingSource.toResult(response, continuation)):
public void getTMessagesPage(TMessageKey pageKey, int pageSize, TMessagePagingSource pagingSource, @NonNull Continuation<? super PagingSource.LoadResult<TMessageKey, TMessage>> continuation) {
List<TMessage> tMessages = new ArrayList<TMessage>();
...
getTMessagesPageStep(281126480l, 0, pageKey, limit, tMessages, pagingSource, continuation);
}
public void getTMessagesPageStep(long chatID, long fromMessageId, TMessageKey pageKey, int limit, List<TMessage> tMessages, TMessagePagingSource pagingSource, @NonNull Continuation<? super PagingSource.LoadResult<TMessageKey, TMessage>> continuation) {
...
client.send(new TdApi.GetChatHistory(chatID, fromMessageId, offset, lLimit, false), new Client.ResultHandler() {
@Override
public void onResult(TdApi.Object object) {
...
if(msgCount > 0){
getTMessagesPageStep(chatID, lastMessageId, pageKey, limit, tMessages, pagingSource, continuation);
} else{
getTMessagesPageStepResult(chatID, pageKey, limit, tMessages, pagingSource, continuation);
}
}
});
}
public void getTMessagesPageStepResult(long chatID, TMessageKey pageKey, int limit, List<TMessage> tMessages, TMessagePagingSource pagingSource, @NonNull Continuation<? super PagingSource.LoadResult<TMessageKey, TMessage>> continuation) {
...
TMessageResponse response = new TMessageResponse(tMessages, nextPageKey, prevPageKey);
pagingSource.toResult(response, continuation); // Returns the result
}
Result: after the first execution of continuation.resumeWith(result), the program continues to run, but returns an error (maybe because I'm returning null to the load() function?):
Job ScopeCoroutine{Completing}@a273a68 is already complete or completing, but is being completed with CompletedExceptionally[java.lang.IllegalStateException: This mutex is not locked]
After the second call to continuation.resumeWith(result), the program closes itself without printing an error.
Android API 21
I think I'm using Continuation incorrectly, but I haven't found how to do it in Java.
Expected that with the help of Continuation I would be able to correctly pass LoadResult<TMessageKey, TMessage> the result of the load() function without causing errors. Perhaps this can be done without using Continuation
Please tell me I have little experience in writing Android applications