我如何将List <>与带有safeArgs的一对一关系pojo(ROOM实现)传递给目标

2019年6月4日 26点热度 0条评论

这个答案很有帮助,但似乎仍然缺少一些东西。

https://stackoverflow.com/a/56477713/11214643

问题是设置该参数的“操作”方法告诉我,我的List与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构造函数才能进行编译(即使之前不需要构造函数)它是可包裹的)

代码:

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);

最后一个需要注意的技巧是List类的
.toArray()方法如何不包括List本身的行数或项目数,这就是为什么手动将项目数放在代码,在这种情况下使用的是
adapter.getItemCount()方法,但是如果直接使用List <>,则只需使用List的.size()方法。在这种情况下将是
productQuantities.size()