android:使用 CompletableFuture 从 Room 加载列表?

问题描述

由于 AsyncTask() 方法已被弃用,我正在尝试替换它。以前 AsyncTask() 用于将 CardView 从 Room 数据库加载到 RecyclerView 列表中。我正在尝试使用 CompletableFuture() 作为替代,但该列表未加载。 “List getAllCards()”的 Dao 方法在 Android Studio 中给出了一条错误消息“从未使用过该方法的返回值”,因此听起来从未从数据库获取该列表。 Repository 从 viewmodel 中获取 List 方法viewmodel 在 MainActivity 中获取 List 方法调用

我还想避免“ExecutorService.submit(() - > cardDao()).get()”来加载列表,因为它是阻塞的。我在下面展示了运行良好的 ExecutorService submit(() 方法,以供参考。

由于列表未加载,我在这里遗漏了什么?

Repository

public List<Card> getAllCards() {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

        CompletableFuture.supplyAsync(() -> {
            List<Card> loadAllCards = new ArrayList<>();
            cardDao.getAllCards();
            return loadAllCards;
        }).thenAcceptAsync(loadAllCards -> getAllCards());
    }
    return null;
}

Dao

@Dao
public interface QuickcardDao {

    @Query("SELECT * FROM cards ORDER BY Sortorder DESC")
    List<Card> getAllCards();
} 

这是我要替换的存储库中的 AsyncTask():

public CardRepository(Application application) {
    CardRoomDatabase db = CardRoomDatabase.getDatabase(application);
    cardDao = db.cardDao();
}

public List<Card> getAllCards() {
    try {
        return new AllCardsAsyncTask(cardDao).execute().get();
    } catch (ExecutionException | InterruptedException e) {
        e.printstacktrace();
    }
    return null;
}

// AsyncTask for reading an existing CardViews from the Room database.
private static class AllCardsAsyncTask extends AsyncTask<Void,Void,List<Card>> {

    private CardDao cardDao;

    AllCardsAsyncTask(CardDao dao) {
        cardDao = dao;
    }

    @Override
    public List<Card> doInBackground(Void... voids) {

        return cardDao.getAllCards();
    }
}

这是我要替换的存储库中的 submit(() 方法

public List<Card> getAllCards() {

    List<Card> newAllCards = null;
    try {
        newAllCards = CardRoomDatabase.databaseExecutor.submit(() -> cardDao.getAllCards()).get();
    }
    catch (InterruptedException | ExecutionException e) {
        e.printstacktrace();
    }
    return newAllCards;
}

// 结束

解决方法

既然你说你不想使用 RxJavacoroutines 并且我不熟悉 CompletableFuture 我想建议你从数据库中获取数据的最简单方法不阻塞 UI thread - 使用 LiveDataLiveData 默认在单独的线程上执行 fetch 操作,然后通知所有观察者。

以下是必要的步骤:

  1. 将此依赖项添加到 gradle

    implementation "androidx.lifecycle:lifecycle-livedata:2.3.1"

  2. 去掉所有与 Asynctask 或 CompletableFuture 相关的代码


  1. 将如下方法添加到您的 @Dao 注释类

     @Dao
     public interface QuickcardDao {
    
     @Query("SELECT * FROM cards ORDER BY Sortorder DESC")
     LiveData<List<Card>> getAllCards();}
    

  1. 将方法添加到您的 Repo 中,如下所示

    public LiveData<List<Card>> getAllCards() {
            return cardDao.getAllCards();   
         }
    

  1. 向您的 ViewModel 添加方法,如下所示:

    public LiveData<List<Card>> getAllCardsLive{ return repo.getAllCards(); }


  1. 在您的活动中观察 LiveData

    `viewModel.getAllCardsLive().observe(getViewLifeycleOwner(),cards ->{
         // submit obtained cards lit to your adapter
     }`