Quero usar o Paging Library 3 em conjunto com o LiveData do Java. A documentação explica como usar, Guava Futures, RxJava Singles and Kotlin Coroutinesmas não como usar com o LiveDataJava. Provavelmente posso As várias PagingSourceclasses fornecem load, loadSinglee loadFuture.
O loadexemplo em Kotlin carrega dados usando retrofit com uma co-rotina e pode, portanto, retornar um LoadResultobjeto. Mas com LiveData, eu preciso fazer uma chamada assíncrona de retrofit e definir o valor no LiveDataobjeto. Não existe um loadmétodo de utilitário separado para o LiveDataque existe para RxJavae Guava. Então, como eu posso conseguir isso usando LiveDataa partir de Java?
package org.metabrainz.mobile.data.repository;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.paging.PagingSource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.metabrainz.mobile.data.sources.Constants;
import org.metabrainz.mobile.data.sources.api.MusicBrainzServiceGenerator;
import org.metabrainz.mobile.data.sources.api.SearchService;
import org.metabrainz.mobile.data.sources.api.entities.mbentity.MBEntity;
import org.metabrainz.mobile.data.sources.api.entities.mbentity.MBEntityType;
import org.metabrainz.mobile.presentation.features.adapters.ResultItem;
import org.metabrainz.mobile.presentation.features.adapters.ResultItemUtils;
import java.util.ArrayList;
import java.util.List;
import kotlin.coroutines.Continuation;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class SearchPagingSource extends PagingSource<Integer, ResultItem> {
@NonNull
private final static SearchService service = MusicBrainzServiceGenerator
.createService(SearchService.class, true);
@NonNull
private MBEntityType entity;
@NonNull
private String searchTerm;
public SearchPagingSource(@NonNull MBEntityType entity, @NonNull String searchTerm) {
this.entity = entity;
this.searchTerm = searchTerm;
}
@NotNull
@Override
public LiveData<LoadResult<Integer, ResultItem>> load(@NotNull LoadParams<Integer> loadParams,
@NotNull Continuation<? super LoadResult<Integer, ResultItem>> continuation) {
Integer pageSize = loadParams.getLoadSize();
Integer offset = loadParams.getKey() == null ? 0 : loadParams.getKey();
MutableLiveData<LoadResult<Integer, ResultItem>> resultsLiveData = new MutableLiveData<>();
service.searchEntity(entity.name, searchTerm, pageSize.toString(),
String.valueOf(offset * pageSize))
.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(@NonNull Call<ResponseBody> call,
@NonNull Response<ResponseBody> response) {
try {
List<ResultItem> data = ResultItemUtils
.getJSONResponseAsResultItemList(response.body().string(), entity);
LoadResult.Page<Integer, ResultItem> loadResult
= new LoadResult.Page<>(data, Math.max(0, offset - pageSize),
offset + pageSize, LoadResult.Page.COUNT_UNDEFINED,
LoadResult.Page.COUNT_UNDEFINED);
resultsLiveData.setValue(loadResult);
} catch (Exception e) {
e.printStackTrace();
LoadResult.Error<Integer, ResultItem> error = new LoadResult.Error<>(e);
resultsLiveData.setValue(error);
}
}
@Override
public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
}
});
return resultsLiveData;
}
}
No entanto, isso trava no tempo de execução
org.metabrainz.android E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.metabrainz.android, PID: 2222
java.lang.ClassCastException: androidx.lifecycle.MutableLiveData cannot be cast to androidx.paging.PagingSource$LoadResult at androidx.paging.PageFetcherSnapshot.doInitialLoad(PageFetcherSnapshot.kt:302) at androidx.paging.PageFetcherSnapshot$pageEventFlow$1.invokeSuspend(PageFetcherSnapshot.kt:149) at androidx.paging.PageFetcherSnapshot$pageEventFlow$1.invoke(Unknown Source:10) at androidx.paging.CancelableChannelFlowKt$cancelableChannelFlow$1.invokeSuspend(CancelableChannelFlow.kt:35) at androidx.paging.CancelableChannelFlowKt$cancelableChannelFlow$1.invoke(Unknown Source:10) at kotlinx.coroutines.flow.ChannelFlowBuilder.collectTo$suspendImpl(Builders.kt:327)
at kotlinx.coroutines.flow.ChannelFlowBuilder.collectTo(Unknown Source:0)
at kotlinx.coroutines.flow.internal.ChannelFlow$collectToFun$1.invokeSuspend(ChannelFlow.kt:33)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:69)
at kotlinx.coroutines.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:321)
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:26)
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:109)
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:158)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:54)
at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47) at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
at androidx.lifecycle.BlockRunner.maybeRun(CoroutineLiveData.kt:174)
at androidx.lifecycle.CoroutineLiveData.onActive(CoroutineLiveData.kt:240)
at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:437) at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:395)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361) at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300) at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339) at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145) at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131) at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68) at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:144) at androidx.lifecycle.ReportFragment.onStart(ReportFragment.java:109) at android.app.Fragment.performStart(Fragment.java:2637) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1312) at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1549) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1611) at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3039) at android.app.FragmentManagerImpl.dispatchStart(FragmentManager.java:2996) at android.app.FragmentController.dispatchStart(FragmentController.java:189) at android.app.Activity.performStart(Activity.java:7007) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2867) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2986) at android.app.ActivityThread.-wrap11(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1671)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:206)
at android.app.ActivityThread.main(ActivityThread.java:6784)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:852)
Eu abri uma solicitação de recurso para enviar uma fonte de paginação LiveData com a biblioteca de paginação. Recebi a seguinte resposta dos desenvolvedores do Google.
As amostras de Java Guava em d.android.com são para Guava + LiveData, no equivalente da corrotina usamos: ListenableFuture da Guava como uma primitiva assíncrona que retorna um único resultado (equivalente a uma Coroutine ou RxJava Single) e LiveData para vários resultados / fluxo de resultados (equivalente a Fluxo de Kotlin ou RxJava observável).
Fui recomendado para escrever algo nas linhas do seguinte trecho de código I se eu quisesse usar o LiveData.
abstract class SearchPagingSource extends RxPagingSource<Integer, ResultItem>() {
@NotNull
public abstract LiveData<LoadResult<Integer, ResultItem>> loadLiveData(params: LoadParams<Key>);
@NotNull
@Override
public Single<LoadResult<Integer, ResultItem>> loadSingle(@NotNull LoadParams<Integer> loadParams) {
return loadLiveData(params).toRxJavaSingle(); // You must implement this bit!
}
}
O LiveDatausado no snippet acima deve ser umSingleLiveEvent
PS: Os desenvolvedores do Google estão abertos para reconsiderar sua posição sobre o envio disso na própria biblioteca se mais desenvolvedores solicitarem. O tíquete do rastreador de problemas do Google relevante é este .
Jana Duggar foi aberta sobre sua busca pelo amor. Aqui está tudo o que ela disse sobre o assunto e sua janela de cinco anos para o casamento.
O astro de 'Outlander', Sam Heughan, revelou recentemente o que vai levar do set para relembrar Jamie Fraser, o papel que o tornou uma estrela.
'She Loves You' foi escrita em uma hora, gravada em um dia, e foi a música dos Beatles com uma de suas melhores apresentações de sua carreira.
Dolly Parton e sua avó Bessie tiveram um relacionamento especial. Vovó Parton estava muito doente, mas isso não impediu Dolly de pregar uma peça nela.
Você pode achar que o carvalho ou a nogueira são madeiras resistentes, mas quando se trata da madeira mais dura do mundo, elas nem chegam perto.
O oceano é repleto de beleza, mas também esconde algumas das criaturas marinhas mais assustadoras do planeta. Muitos desses animais espreitam nas profundezas do oceano, no mundo escuro e de alta pressão do fundo do mar.
Se você está enfrentando criaturas hostis ou se preparando para cenários PvP, conhecer os melhores encantamentos de espada no Minecraft pode te dar uma grande vantagem. Encantar espadas permite causar mais dano, aumentar a quantidade de itens obtidos de criaturas e prolongar a durabilidade da sua espada.
Quando as pessoas falam sobre países socialistas, geralmente imaginam o controle total do governo e a ausência de propriedade privada. Mas, na prática, as economias socialistas variam muito.
“Children” traz uma participação especial de grande nome e algumas notícias devastadoras
Este RAV4 está em excelentes condições e está preparado para um jogo de cadeiras musicais.
Imagens de drone capturaram bombeiros parecendo lutar para apagar o incêndio.
Eyes of Wakanda está diretamente relacionado ao MCU, além de atualizações sobre X-Men '97, What If..., Demolidor e muito mais.
O anel de noivado de Kate Middleton pertenceu à Princesa Diana antes do Príncipe William pedi-la em casamento. Descubra tudo o que há para saber sobre a peça histórica aqui.
John Cleese se casou com sua esposa, Jennifer Wade, em 2012. Aqui está tudo o que você precisa saber sobre a esposa de John Cleese, Jennifer Wade.
Patton Oswalt se casou com sua esposa, a também atriz Meredith Salenger, em 2017. Aqui está tudo o que você precisa saber sobre a esposa de Patton Oswalt, Meredith Salenger.
Mena Suvari é casada com o marido Michael Hope desde 2018. Aqui está tudo o que você precisa saber sobre o marido de Mena Suvari.
Isso me atinge De repente, como tantas vezes acontece É o meio do caminho tudo de novo <Não, não aquele no Pacífico, seu marrom, aquele no carnaval> Todas as manchetes em voz alta…..
Em 2022, com o lançamento do GPT-3, a habilidade de escrita parece se tornar menos importante. Com a IA, pessoas com redação ruim também podem gerar funcionários de qualidade.
No mundo acelerado e competitivo de hoje, a carreira desempenha um papel significativo no crescimento pessoal, na estabilidade financeira e na satisfação geral com a vida. No entanto, muitos indivíduos encontram-se presos em um ciclo implacável de estagnação e insatisfação, definhando gradualmente em suas vidas profissionais.
Na semana passada, notei um comunicado de imprensa, enviado via PressGazette (um site de notícias da mídia britânica). O artigo anunciava que a Acast, a empresa de publicidade e hospedagem de podcast Scandi, lideraria um consórcio de "provavelmente os editores mais influentes" em podcasting.