【问题标题】:Fetching Room relational database values with LiveData Transformations使用 LiveData 转换获取 Room 关系数据库值
【发布时间】:2018-07-08 04:41:06
【问题描述】:

刚接触 Android 和 Java,正在尝试通过制作应用来学习。但现在我被困在正确获取关系数据并在 RecyclerView 中显示它(使用 ListAdapter 和 Infinite Scroll)。

这是我到目前为止所做的事情的要点。

实体:
项目:

@Entity(...)
public class Item {

    @PrimaryKey(autoGenerate = true)
    private long item_id;

    @SerializedName("title")
    @Expose
    private String title = "";

    @Ignore
    @SerializedName("labels")
    @Expose
    private List<String> tags;

    ...
    }

标签:

@Entity(...)
public class Tag {

    @PrimaryKey(autoGenerate = true)
    private long id;

    @ColumnInfo(name = "tag_name")
    private String tagName;
    ...
}

关系:

@Entity(...)
public class ItemTags {

    private long item_id;

    private long tag_id;
    ...
}

改造:

public class ApiClient {
    // Init in Constructor
    private final MutableLiveData<List<Item>> mObservableData;
    ...

    public LiveData<List<Item>> getObservableData() {
        return mObservableData;
    }

    public void onResponse(...) {
        ...
        mObservableData.postValue(responseBody.getItems());

    }
}

存储库:插入到数据库中。

public void getNetworkCallback() {
    if (isFirstCallbackNeeded()) {
        Log.d(TAG, "getNetworkCallback: Called");
        mClient.getFirstCallback();
        insertItemsToDb();
    }
}

private void insertItemsToDb() {
    LiveData<List<Item>> downloadedData = mClient.getObservableData();
        if (items != null) {
            mExecutors.diskIO().execute(() -> {
                List<Long> itemIds = insertAllItems(items);

                for (int i = 0; i < items.size(); i++) {
                    long itemId = itemIds.get(i);
                    Log.d(TAG, "insertItemsToDb: " + itemId);

                    if (itemId != -1) {
                        List<String> labelNames = items.get(i).getTags();
                        for (String labelName : labelNames) {
                            insertUniqueTagName(new Tag(labelName));

                            long tagId = fetchIdByTagName(labelName);
                            insertRelational_ItemTags(new ItemTags(itemId, tagId));
                        }
                    }
                }
        }
    });
}

一切都很好。当数据库为空并得到响应后,数据成功插入数据库。

但是,每当我尝试获取与每个项目相关的标签,以显示在 RecyclerView 中时,同时使用Transformations.map,返回的Tags 列表为null 或为空。

public LiveData<List<Item>> fetchAllItems() {
    LiveData<List<Item>> itemLiveData = mItemDao.fetchAllItems();
    itemLiveData = Transformations.map(itemLiveData, input -> {
        for (Item item : input) {
            mExecutors.diskIO().execute(() -> {
                long itemId = item.getItem_id();
                Log.d(TAG, "getTransformedObservableItems: itemId: " + itemId);
                List<String> tagNames = fetchRelationalTagNameById(itemId);
                Log.d(TAG, "getTransformedObservableItems: tagNames: " + tagNames);
                item.setTags(tagNames);
            });
        }
        return input;
    });

    return itemLiveData;
}

日志:

getTransformedObservableItems: itemId: 1
getTransformedObservableItems: tagNames: []
getTransformedObservableItems: itemId: 2
getTransformedObservableItems: tagNames: []
...

值得一提的是,我只观察道中的物品清单

@Query("SELECT * FROM item")
LiveData<List<Item>> fetchAllItems();

视图模型:

public ItemViewModel(ApiRepository apiRepository) {
    mObservableLiveData = apiRepository.fetchAllItems();
}

public LiveData<List<Item>> getObservableLiveData() {
    return mObservableLiveData;
}

活动:

repository.getNetworkCallback();
// RecyclerView ListAdapter
mViewModel.getObservableLiveData().observe(this, adapter::submitList);

我在这里做错了什么?逻辑正确吗?任何建议都有帮助。

谢谢。


更新:

经过几次尝试,我发现在insertItemsToDb() onChanged() 方法中对LiveData&lt;List&lt;Item&gt;&gt; fetchAllItems() 使用removeObserver(),我能够达到结果。

但当我使用Executors 时,遗憾的是,后台线程中不允许使用removeObserver()

有人有什么建议吗?


解决方案 @Pycpik 建议的Transformations#switchMap

public LiveData<List<Item>> fetchAllTransformedItems() {
    LiveData<List<Item>> itemLiveData = fetchAllItems();
    itemLiveData = Transformations.switchMap(itemLiveData, input -> {
        final MutableLiveData<List<Item>> itemListMutableData = new MutableLiveData<>();
        mExecutors.diskIO().execute(() -> {
            for (Item item : input) {
                long itemId = item.getItem_id();
                List<String> tagNames = fetchRelationalTagNameById(itemId);
                item.setTags(tagNames);
            }
            itemListMutableData.postValue(input);
        });
        return itemListMutableData;
    });

    return itemLiveData;
}

【问题讨论】:

    标签: android android-room android-livedata


    【解决方案1】:

    我的情况并不完全相同,但下面是我如何使用switchMap 和 RxJava 处理与关系获取数据的方法。也许它可以帮助你。

    public LiveData<List<Item>> fetchAllItems() {
        LiveData<List<Item>> itemLiveData = mItemDao.fetchAllItems();
        itemLiveData = Transformations.switchMap(itemLiveData, input -> {
            MutableLiveData<List<Item>> mutableLiveData = new MutableLiveData<>();
            Completable.fromAction(() -> {
                for (Item item : input) {
                    long itemId = item.getItem_id();
                    Log.d(TAG, "getTransformedObservableItems: itemId: " + itemId);
                    List<String> tagNames = fetchRelationalTagNameById(itemId);
                    Log.d(TAG, "getTransformedObservableItems: tagNames: " + tagNames);
                    item.setTags(tagNames);
                }
            })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(() -> {mutableLiveData.postValue(input);});
            return mutableLiveData;
        });
        return itemLiveData;
    }
    

    【讨论】:

    • 是的,我正在寻找有关Transformations.switchMap 工作原理的示例,这正是我所需要的。发布解决方案。
    【解决方案2】:

    我可以试试前台线程 或部分代码使用它

    activity.runOnUiThread(() ->{
    });
    

    【讨论】:

    • 但我没有参加活动。 fetchAllItems 在存储库类中。
    • 将 this(context) 传递给这个类并将其转换为 Activity
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多