3

我正在编写一个运行非本地服务的 android 应用程序,以便从 Internet 获取数据。我有一个绑定到所述服务并检索 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 类添加了代码:

公共类 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);
    }
}

}

任何指针?

如果您需要任何信息,请随时询问具体信息!

4

4 回答 4

3

该问题似乎是由 Order 类的两个 Integer 属性引起的。其中之一从未初始化,因此为空。将其写入 Parcel 时,它失败导致整个函数失败,并导致结果列表中弹出空值。奇怪的是这并没有抛出任何异常。

将我的 Integer 属性改回 int 可以解决问题(因为 int 永远不会为空)。由于我确实需要维护 Integer 类型,因此我通过将包裹中的空值作为值 -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);
        }
    }
}
于 2011-08-26T14:07:14.813 回答
1

这可能是一个反序列化问题。你能告诉我们来自服务(xml/json)的序列化响应吗?

于 2011-08-25T14:33:42.450 回答
1

您必须提供更多代码才能确定,但​​您必须确保要在服务之间传输的每个对象都正确实现 Parcelable。

例如,一个ArrayList没有实现接口,你必须扩展它并做必要的管道以使其工作。

这一切的例子在这里。

于 2011-08-25T14:59:09.883 回答
0

尝试传递一个订单数组。

于 2011-08-26T08:18:04.193 回答