2016-08-14 3 views
0

Ich habe mich schon ein wenig umgeschaut, aber ich hatte kein Glück, also würde ich gerne Ihre Meinung dazu haben, vor allem um zu wissen, ob ich in die falsche Richtung gehe.Bestückung Adapter nach Fertigstellung asynctask

Ich habe ein Fragment, das einen Adapter instanziiert und ihm eine Arraylist von Objekten übergibt. Die Liste der Objekte verweist auf andere Ressourcen, die vom Server abgerufen werden müssen, damit sie angezeigt werden können. Also für jedes Objekt der Arraylist, innerhalb des Adapters, rufe ich eine asynctask auf, um diese Informationen abzurufen und das Adapterelement aufzufüllen.

Leider ergibt dies nur das letzte Element des Arraylsit mit allen Informationen, während das andere (in meinem Beispiel habe ich nur zwei Elemente in der Liste) leer ist. Mein Gefühl ist, dass ich zweimal das gleiche Adapterelement überschreibe, und daher sehe ich nur das zuletzt abgerufene Objekt.

Mein Adapter verwendet das ViewHolder-Designmuster, sodass ich in der Funktion getView ein Objekt der privaten Klasse ViewHolderItem instanziiere, die Verweise auf alle Layoutelemente enthält. Ich verwende dann dieses viewHolderItem in all meinem onPostExecute, um das Adapterelement aufzufüllen.

Dies ist der Code meiner ViewHolder Artikel:

private static class ViewHolderItem{ 
    protected Button leaveFeedback, accept, reject; 
    protected LinearLayout userInfo, rideInfo, pickupLayout, buttons; 
    protected TextView pickupTimeText; 
    protected PickupTime pickupTime; 
} 

Das ist mein getView, die die uuml sammelt, die viewholderitem Einrichtung und startet die asynctasks (die Zeilen nach dem Kommentar abrufen Passagier info):

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

Und das ist eine meiner AsyncTask Klassen:

/** 
* 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); 
    } 
} 

Die Funktion demand.populateView() ist eine Funktion, der ich das viewHolderItem mit den Viewreferenzen übergebe, damit ich die Informationen in ihnen füllen kann.

+3

Drei AsyncTasks pro Element? Ihr Akkuverbrauch darf nicht zu glücklich sein ... Können Sie die API nicht umstrukturieren? –

+1

'Ich rufe eine asynctask auf, um diese Informationen abzurufen und das Adapterelement aufzufüllen. Was meinst du mit Adapterartikel? Bevor Sie sagten, Sie hätten eine Array-Liste mit Objekten. Sie sollten eine andere Arraylist mit derselben Größe füllen und die Ergebnisse dort eingeben. Rufen Sie dann afapter notifyDatasetChanged auf. Sie speichern die Ergebnisse in einem Array, während Sie sie beim Scrollen verlieren. – greenapps

+1

Sie sollten den asynchronen Tasks einen zusätzlichen Parameter "i" geben, da sie jetzt nicht wissen, für welches Element sie gestartet wurden und wo sie das Ergebnis ablegen können. – greenapps

Antwort

0

Es stellte sich heraus, dass ich den Adapter nicht korrekt verwendete, aber dank @greenapps Eingaben konnte ich mein Problem lösen.

Grundsätzlich habe ich die Variable viewHolderItem in der getView-Funktion verschoben und über den Konstruktor an alle meine AsyncTasks übergeben, damit sie das Adapterelement auffüllen können, sobald sie das Ergebnis vom Server erhalten haben.

Als Beispiel ist dies eine meiner AsyncTask Klassen nach den oben beschriebenen Modifikationen:

/** 
* Download the JSON of the demand 
*/ 
private class GetDemand extends GetRequest { 

    private int passengershipID; 
    private ViewHolderItem viewHolderItem; 

    public GetDemand(int passengershipID, ViewHolderItem viewHolderItem){ 
     this.passengershipID = passengershipID; 
     this.viewHolderItem = viewHolderItem; 
    } 

    @Override 
    protected void onPostExecute(ServerResponseObject serverResponseObject){ 
     Demand demand = GsonCustomBuilder.getGson().fromJson(
       serverResponseObject.getJSONObject().toString(), Demand.class); 
     Passengership passengership = passengershipsHashMap.get(passengershipID); 
     passengership.setDemand(demand); 
     demand.populateView(viewHolderItem.rideInfo); 
    } 
} 

Wie Sie im Code sehen können, habe ich den Konstruktor, die ich die viewHolderItem zum AsyncTask passieren verwenden . Schließlich verwende ich in onPostExecute das viewHolderItem, um die abgerufenen Informationen aufzufüllen.

+0

Das geht nicht, wenn Sie mehr Gegenstände haben, als Sie sehen können. Im Moment hast du nur zwei Dinge, die du gesagt hast, also sind beide immer sichtbar. Aber für einen Test fügen Sie viel mehr Elemente hinzu, so dass der Benutzer scrollen muss. Sie werden feststellen, dass Ihr Ansatz dann schief geht. Was Sie stattdessen tun sollten, habe ich Ihnen bereits in meinem ersten Kommentar gesagt. – greenapps

Verwandte Themen