【发布时间】:2016-08-14 16:20:38
【问题描述】:
我一直在环顾四周,但运气不佳,所以我想听听您对此的看法,尤其是想知道我是否走错了方向。
我有一个片段实例化一个适配器,将一个对象数组列表传递给它。对象列表引用必须从服务器检索才能显示的其他资源。因此,对于数组列表的每个对象,在适配器内部,我调用一个异步任务来检索这些信息并填充适配器项。
不幸的是,这仅导致数组的最后一个元素包含所有信息,而另一个(在我的示例中,列表中只有两个元素)为空。我的感觉是我覆盖了两次相同的适配器项,因此我只看到最后检索到的对象。
我的适配器使用 ViewHolder 设计模式,因此,在 getView 函数中,我实例化了 ViewHolderItem 私有类的对象,其中包含对所有布局元素的引用。然后我在我的所有 onPostExecute 中使用这个 viewHolderItem 来填充适配器项。
这是我的 ViewHolder 项的代码:
private static class ViewHolderItem{
protected Button leaveFeedback, accept, reject;
protected LinearLayout userInfo, rideInfo, pickupLayout, buttons;
protected TextView pickupTimeText;
protected PickupTime pickupTime;
}
这是我的 getView,它收集视图引用、设置 viewholderitem 并启动 asynctasks(评论后的行检索乘客信息):
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
// First let's verify the view is not null
if (view == null) {
// This a new view we inflate the new layout
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.ride_passenger_item, viewGroup, false);
viewHolderItem = new ViewHolderItem();
viewHolderItem.userInfo = (LinearLayout) view.findViewById(R.id.user_info);
viewHolderItem.rideInfo = (LinearLayout) view.findViewById(R.id.ride_info);
viewHolderItem.buttons = (LinearLayout) view.findViewById(R.id.btns);
viewHolderItem.leaveFeedback = (Button) view.findViewById(R.id.leave_feedback);
viewHolderItem.pickupLayout = (LinearLayout) view.findViewById(R.id.pickup_layout);
viewHolderItem.pickupTimeText = (TextView) view.findViewById(R.id.pickup_time);
viewHolderItem.accept = (Button) view.findViewById(R.id.accept);
viewHolderItem.reject = (Button) view.findViewById(R.id.reject);
// store the holder with the view.
view.setTag(viewHolderItem);
}
else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolderItem = (ViewHolderItem) view.getTag();
}
final Passengership passengership = passengerships.get(i);
/** retrieve passenger info **/
new GetDemand().execute(demandAPI.getDemand());
new GetPassenger().execute(userAPI.getUser(passengership.getPassenger()));
new GetRide().execute(rideAPI.getRide());
/**
* if we are displaying pending passenger request, proposed by the driver
* we need to enable the accept reject button
**/
if(type.equals(Status.PENDING) && !passengership.isProposedByDriver())
buildAcceptRejectButtons(passengership);
this.passengershipID = passengership.getId();
return view;
}
这是我的 AsyncTask 类之一:
/**
* Download the JSON of the demand
*/
private class GetDemand extends GetRequest {
@Override
protected void onPostExecute(ServerResponseObject serverResponseObject){
Demand demand = GsonCustomBuilder.getGson().fromJson(
serverResponseObject.getJSONObject().toString(), Demand.class);
demand.populateView(viewHolderItem.rideInfo);
}
}
demand.populateView() 基本上是一个函数,我将包含视图引用的 viewHolderItem 传递给它,以便我可以在其中填充信息。
【问题讨论】:
-
每个项目三个 AsyncTasks?你的电池使用一定不要太高兴……你能不重构API吗?
-
I call an asynctask to retrieve these information and populate the adapter item.。适配器项目是什么意思?在你说你有一个包含对象的数组列表之前。您应该填充另一个具有相同大小的数组列表并将结果放在那里。然后调用之后的 notifyDatasetChanged。您将结果保存在一个数组中,否则滚动时会丢失它们。 -
你应该给异步任务一个额外的参数
i,因为现在他们不知道他们从哪个项目开始以及完成后将结果放在哪里。 -
viewHolderItem。你把它作为你的活动变量?错误的。使其成为 getView() 的局部变量。这将阻止您在其他地方使用它。 -
@greenapps 感谢您的回答并为您的困惑感到抱歉。我这句话的意思是异步任务是在适配器内启动的,我现在明白他们不知道数据属于哪个项目。所以我理解你的意思。我要试试你说的。对于 viewHolderItem 而言,它在适配器中,而不是在活动中。
标签: java android listview android-asynctask adapter