簡體   English   中英

當通過IPC將對象列表從服務傳遞到活動時,可分配項目消失

[英]Parcelable items disappearing when passing list of objects from service to activity via IPC

我正在編寫一個運行非本地服務的Android應用程序,以便從互聯網上獲取數據。 我有一個綁定到所述服務的活動,並檢索Order對象列表以顯示它們。

將列表從服務傳遞到活動時似乎出現了問題。 雖然這對我來說似乎很簡單。

問題

列表中的所有項目,但索引1處的項目都是空值。

調試從活動接收的列表的視圖

調試顯示服務函數具有正確的列表並返回正確的列表:

調試從服務發送的列表視圖

這是返回列表的服務中的函數:

public List<Order> getOrders() throws RemoteException {
    synchronized(service.orders) {
        // service.orders returns a hashmap<Integer, Order>
        // where the key is the ID of the order
        // The function returns a simple list, so we parse to an ArrayList
        List<Order> result = new ArrayList<Order>(service.orders.values()); 

        return result;
    }
}

這是Activity中調用服務並檢索列表的函數(其中api是綁定到服務的結果):

handler.post(new Runnable() {
    public void run() {
        try {
            List<Order> result = api.getOrders();

            displayOrders(result);

        } catch (Throwable t) {
            Log.e(TAG, "Error while updating the UI with orders", t);
        }
    }
});

這讓我感到非常難過,因為我還有一個活動來查看客戶和一個返回客戶列表的服務功能,並且運行完美。 兩者之間的主要區別在於Customer沒有任何自定義對象屬性,而Order有一些。

編輯:為Order類添加了Parcelable實現(通過刪除大多數原始屬性簡化):

/*
* Parcelabe interface implementation
*/

public static final Creator<Order> CREATOR = new Creator<Order>() {
    public Order createFromParcel(Parcel source) {
        return new Order(source);
    }

    public Order[] newArray(int size) {
        return new Order[size];
    }
};

public Order(Parcel source) {
    ID = source.readInt();
    OrderID = source.readInt();
    CustomerID = source.readInt();

    TotalAmount = source.readDouble();
    TotalProducts = source.readDouble();

    OrderDate = source.readString();
    InvoiceDate = source.readString();
    DeliveryDate = source.readString();

    // Custom objects
    Customer = source.readParcelable(Customer.class.getClassLoader());

    History = new ArrayList<OrderHistory>();
    source.readTypedList(History, OrderHistory.CREATOR);

    State = source.readParcelable(OrderState.class.getClassLoader());
}

public int describeContents() {
    return Order.class.hashCode();
}

public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(ID);
    dest.writeInt(OrderID);
    dest.writeInt(CustomerID);

    dest.writeDouble(TotalAmount);
    dest.writeDouble(TotalProducts);    

    dest.writeString(OrderDate);
    dest.writeString(InvoiceDate);
    dest.writeString(DeliveryDate);

    // Custom object
    dest.writeParcelable(Customer, flags);
    dest.writeParcelable(State, flags);
    dest.writeTypedList(History);
}

編輯:為OrderList類添加了代碼:

public class OrderList extends ArrayList實現Parcelable {

/**
 * 
 */
private static final long serialVersionUID = 417326483896340670L;

public OrderList() {

}


public OrderList(Parcel in) {
    readFromParcel(in);
}


/*
 * Parcelabe interface implementation
 */

public OrderList(Collection<Order> values) {
    this.addAll(values);
}


@SuppressWarnings("unchecked")
public static final Parcelable.Creator<OrderList> CREATOR = new Parcelable.Creator<OrderList>() {
    public OrderList createFromParcel(Parcel in) {
        return new OrderList(in);
    }

    public OrderList[] newArray(int arg0) {
        return null;
    }

};

private void readFromParcel(Parcel in) {
    this.clear();

    //First we have to read the list size
    int size = in.readInt();

    //Reading remember that we wrote first the Name and later the Phone Number.
    //Order is fundamental

    for (int i = 0; i < size; i++) {
        Order o = new Order();
        o = in.readParcelable(Order.class.getClassLoader());
        this.add(o);
    }

}

public int describeContents() {
    return 0;
}

public void writeToParcel(Parcel dest, int flags) {
    int size = this.size();
    // We have to write the list size, we need him recreating the list
    dest.writeInt(size);

    // We decided arbitrarily to write first the Name and later the Phone Number.
    for (int i = 0; i < size; i++) {
        Order o = this.get(i);
        dest.writeParcelable(o, flags);
    }
}

}

有什么指針嗎?

如果您需要,請隨時詢問具體信息!

問題似乎是由Order類的兩個Integer屬性引起的。 其中一個從未初始化,因此為null。 將其寫入Parcel時,它會導致整個函數失敗,並導致在結果列表中彈出空值。 奇怪的是,這不會引發任何異常。

將我的Integer屬性更改回int修復了問題(因為int永遠不為null)。 由於我確實需要維護Integer類型,因此我通過將parcel中的空值作為值-1來修復它。

這歸結為:

public class Order implements Parcelable {
    public Integer ID;
    public Integer OrderID;

    public Order(Parcel source) {
        ID = source.readInt();
        if (ID.intValue() == -1) {
            ID = null;
        }

        OrderID = source.readInt();
        if (OrderID.intValue() == -1) {
            OrderID = null;
        }
    }

    public void writeToParcel(Parcel dest, int flags) {
        if (ID == null) {
            dest.writeInt(-1);
        } else {
            dest.writeInt(ID);
        }

        if (OrderID == null) {
            dest.writeInt(-1);
        } else {
            dest.writeInt(OrderID);
        }
    }
}

這可能是一個反序列化問題。 你能告訴我們服務的序列化響應(xml / json)嗎?

您必須提供更多代碼才能確定,但​​您必須確保要在服務之間傳輸的每個對象都正確實現Parcelable。

例如ArrayList沒有實現接口,您必須擴展它並執行必要的管道以使其工作。

這里所有這些的例子。

嘗試傳遞一系列訂單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM