如何将具有一对一关系 pojo(ROOM 实现)和 safeArgs 的 List<> 传递到目的地

How Do I pass a List<> with a one to one relation pojo (ROOM implementation) with safeArgs to the destination

这个回答帮了大忙,但好像还缺什么。

问题是设置参数的 'action' 方法告诉我我的列表与 navigation.xml 中定义的列表类型不同,如果我尝试编写xml 作为 List 的参数,碰巧 safeArgs 不支持该类型(如果它是由 RecyclerViewAdapters 管理的最常见类型,那就很奇怪了),我还尝试将我的 List<> 转换为 ArrayList<> 但什么也没有。

我的代码:

<fragment
    android:id="@+id/product_list_fragment"
    android:name="com.example.myapp.ui.ProductListFragment"
    android:label="@string/product_list_title"
    tools:layout="@layout/fragment_product_list">
    <argument
        android:name="quote"
        app:argType="integer"
        android:defaultValue="0"
        />
    <argument
        android:name="productList"
        app:argType="com.example.myapp.data.pojos_entities.ProductQuantity[]"
        />

</fragment>


public class ProductQuantity {

    @Embedded
    public Quantity mQuantity_;

    @Relation(
            parentColumn = "child_product_id",
            entityColumn = "product_id"
    )
    public Product mProduct_;
}

所以我终于想出了一个解决方案,它看起来像这样:

但它并不像那一行那么简单。 对于 List<ProductQuantity> productQuantities,为了能够将其自身转换为 Parcelable Array[](不是 Array[] 或 ArrayList,它们不相同),Pojo(在本例中为 ProductQuantity.class)必须实现一个 Parcelable。像这样:

实施后,只需按 alt + Enter 即可实施所有必要的方法。

但是,这还不是全部。

在用于关系查询的 ROOM Pojo 中实现方法的问题在于它不会编译,因此您接下来需要做的是在 Parcelable 实现创建的每个方法之上使用 @Ignore 接口.

最后你会注意到它仍然没有编译,并且出于某种原因,即使你忽略了 Parcelable 所需的构造函数,你也必须为 ROOM 创建一个 EMPTY 构造函数才能编译(即使在成为 Parcelable 之前不需要构造函数)

代码:

public class ProductQuantity implements Parcelable {

    @Embedded
    public Quantity mQuantity_;

    @Relation(
            parentColumn = "child_product_id",
            entityColumn = "product_id"
    )
    public Product mProduct_;


    public ProductQuantity() {
/*Empty constructor required by ROOM*/
    }

    @Ignore
    protected ProductQuantity(Parcel in) {
    }

    @Ignore
    public static final Creator<ProductQuantity> CREATOR = new Creator<ProductQuantity>() {
        @Override
        public ProductQuantity createFromParcel(Parcel in) {
            return new ProductQuantity(in);
        }

        @Override
        public ProductQuantity[] newArray(int size) {
            return new ProductQuantity[size];
        }
    };


/*This methods don't need to be ignored for some reason*/
    @Override
    public int describeContents() {
       return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
    }
}

转换加导航:

            List<ProductQuantity> productQuantities = adapter.getCurrentList();

            ProductQuantity[] productQuantitiesArray = productQuantities
                    .toArray(new ProductQuantity[adapter.getItemCount()]);

            ProductsAndQuantitiesFragmentDirections.ActionProductsAndQuantitiesByQuoteFragmentToProductListFragment direction;

            Log.d(TAG, "onClick: quoteId is: " + quoteId);
            direction = ProductsAndQuantitiesFragmentDirections
                    .actionProductsAndQuantitiesByQuoteFragmentToProductListFragment(productQuantitiesArray).setQuote(quoteId);

            Navigation.findNavController(view).navigate(direction);

最后一个要注意的提示是列表 class 的 .toArray() 方法如何不包括列表本身的行数或项目数,这就是为什么它是最重要的在代码中手动放置项目数量的重要性,在本例中使用了 adapter.getItemCount() 方法,但如果您直接使用 List<>,只需使用 List 的 .size() 方法。在这种特殊情况下将是 productQuantities.size()