2011-08-25 107 views
3

將對象列表中的對象從服務傳遞到活動時,可刪除項目消失我正在編寫一個運行非本地服務以便從Internet獲取數據的Android應用程序。我有一個綁定到所述服務的活動,並檢索Order對象列表以顯示它們。通過IPC

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

的問題

所有列表中的項目,但在指數產品1,是空值。

Debug view of the received list from activity

調試表明我的服務功能具有正確的清單,並返回正確的列表:

Debug view of the list to send from the service

這是在返回列表中的服務功能:

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

這是函數n的調用服務並檢索列表(其中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); 
     } 
    } 
}); 

這已經讓我完全難倒,因爲我也有一個活動來查看客戶和在返回客戶列表的服務上起作用,並且工作完美無瑕。兩者之間的主要區別在於客戶沒有任何自定義對象屬性,而訂單有少數。

編輯:添加Parcelable實施Order類(由除去大部分原始性質的簡化):

/* 
* 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類代碼:

公共類OrderList延伸的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); 
    } 
} 

}

任何指針?

請不要猶豫,要求具體信息,如果你需要任何!

+0

像ReggieBE說,可能是一些待辦事項與系列化,給我們一些更多的代碼... –

+0

郵政'Order'類,或者至少parceling位。 – dmon

+0

默認情況下,ArrayList沒有實現Parcelable,你必須自己擴展這個類。 –

回答

3

該問題似乎是由Order類的兩個Integer屬性造成的。其中一個從未初始化,因此爲空。將其寫入Parcel時,它會導致整個函數失敗,並導致在結果列表中彈出空值。奇怪的是,這並沒有拋出任何例外。

將我的整數屬性改回爲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); 
     } 
    } 
} 
1

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

+0

序列化不成問題。該服務從互聯網上檢索數據,當我調試要返回到Activity的數據時,所有屬性都被正確填充。我的猜測是你把「服務」誤認爲是「網絡服務」。我提到的服務是這裏定義的Android服務:http://developer.android.com/reference/android/app/Service.html –

+1

是的,但Android通過Parcelable接口執行序列化並使用它傳輸數據意圖等之間的活動和/或服務...... –

+0

啊,這就是他的意思。我認爲他的意思是從webservice(xml)到對象的反序列化。 –

1

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

ArrayList for example沒有實現接口,你必須擴展它,並做必要的管道工作。

Example of all this here.

+0

增加了OrderList類,它擴展了ArrayList,就像你給我的例子一樣,但是這仍然不會改變任何東西。如果你喜歡,我可以爲你提供完整的源代碼嗎? –

0

嘗試通過訂單的陣列。