AsyncTask im BaseAdapter läd Thumbbitmaps nicht wie gewünscht

  • 8 Antworten
  • Neuester Beitrag
Diskutiere AsyncTask im BaseAdapter läd Thumbbitmaps nicht wie gewünscht im Android App Entwicklung im Bereich Betriebssysteme & Apps.
C

CoffeeCode

Ambitioniertes Mitglied
Ich habe eine ListView die ich mit einem erweiterten BaseAdapter mir zusammen stelle.
In einer Zeile sollen neben einigen TextViews auch kleine Thumbimages sein die die ersten Bilder anzeigen die sich im jeweiligen Ordner befinden.

Dies funktioniert auch alles jedoch werden nach dem Scrollen die Zeilen recycled und Ordner die keine Bilder haben zeigen Thumbimages an.
Zudem ist das erstellen der Thumbs etwas chaotisch. Anfangs wechseln die Bilder bis die richtigen da sind.
Das Video wird es wohl am besten erklären. [1]

Ich habe versucht die Views in der Zeile mit einem ViewHolder umzusetzen wie es hier beschreiben ist [2]. Das verhalten hat sich aber nicht geändert.

[1] YouTube Video zum beschreiben des Problems
[2] Making ListView Scrolling Smooth | Android Developers
[3] https://gist.github.com/CoffeeCode/9514028
 
Zuletzt bearbeitet:
J

JustinTime

Fortgeschrittenes Mitglied
Poste am besten mal deinen Adapter und wie er befüllt wird dann sehen wir ob der holder richtig implementiert ist etc. :)
 
J

JustinTime

Fortgeschrittenes Mitglied
Du machst es dir in dem Adapter wirklich wahnsinnig kompliziert. :smile:

den block

Code:
 if( ((int)collection.getId()) == activeCollectionId){
            textViewActiveCollection.setVisibility(View.VISIBLE);
            view.setBackgroundColor(context.getResources().getColor(R.color.bg_gray_highlight));
        }
        else{
            textViewActiveCollection.setVisibility(View.INVISIBLE);
            view.setBackgroundColor(0x00000000);
        }
würde ich komplett rausnehmen. Die aktuell zu bauende View invisible zu setzen sieht nach einer eher schlechten Lösung aus.

als nächstes würd ich die Logik des holders ändern

Code:
ViewHolder = holder;
if(view == null){
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.item_collection_row, null);
            holder = new ViewHolder();
            holder.textViewDate = view.findViewById(R.id.textViewDate);
            [B]alle anderen findViewByIds[/B]
            view .setTag(holder);
        }
else {  
   holder = (Holder) view .getTag();
}
holder.textViewDate.settext("blablabla");
holder.textViewLocation .settext("blablabla");
usw.
und dazu dann der simple holder

Code:
 static class ViewHolder {
    public TextView textViewDate, textViewLocation ... ;
    public ImageView imageViewThumb0 , imageViewThumb1 ...;
  }
Die Bilder für die Items würde ich eventuell auslesen wenn du die Collection items speicherst und dann direkt mit in die das objekt schreiben und nicht jedes mal neu lesen wenn die liste gescrollt wird. :smile:

Ich hoffe irgendwas davon hilft dir weiter.
 
C

CoffeeCode

Ambitioniertes Mitglied
ja der code ist erst mal "shitty first draft". Soll erst mal funktionieren.
Die Bilder in den Ordnern können jederzeit ändern daher müsste das dynamisch geschehen.

ich specke den Adapter erst mal etwas ab.

so wie ich den Code jetzt sehe macht es Sinn die gerammten View in den holder zu packen?
Ich verstehe noch nicht ganz den Sinn dieses Design patterns.
 
Zuletzt bearbeitet:
C

CoffeeCode

Ambitioniertes Mitglied
@JustinTime mit deinen Änderungen könnte ich das "jerky loading" Problem lösen. Wenn in einer row die Bilder geladen sind bleiben diese auch.

Was geblieben ist, ist das die recycelten row's die Bilder der alten row behalten.
Eine row zeigt also Bilder an die eigentlich keine anzeigen sollte

Deutlich entschlackter Code:
https://gist.github.com/CoffeeCode/9529258

ich vermute der bug liegt im AsyncTask bei doinBackground()
muss ich hier die imageview hiden wenn sie recyceld wurde und keine Bilder rein müssen?
Code:
      protected void onPostExecute(Bitmap[] result) {

            if(viewHolder.position == this.position) {
                for (int i = 0; i < 4; i++) {
                    if(thumb[i] != null)
                        viewHolder.imageView[i].setImageBitmap(thumb[i]);
                    else
                        viewHolder.imageView[i].setImageResource(R.drawable.ic_action_new);
                }
            }

        }
 
C

CoffeeCode

Ambitioniertes Mitglied
habs so gelöst

Code:
 @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        Collection collection = collectionList.get(i);

        Log.d("and1", "element : " + i);
        ViewHolder holder;

        if(view == null){
            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.item_collection_row, null);
            holder = new ViewHolder();
            holder.name = (TextView) view.findViewById(R.id.textViewName);
            holder.date = (TextView) view.findViewById(R.id.textViewDate);
            holder.location = (TextView) view.findViewById(R.id.textViewLocation);
            holder.active = (TextView) view.findViewById(R.id.textViewActiveCollection);
            holder.count = (TextView) view.findViewById(R.id.textViewImageCount);
            holder.imageView[0] = (ImageView) view.findViewById(R.id.imageViewThumb0);
            holder.imageView[1] = (ImageView) view.findViewById(R.id.imageViewThumb1);
            holder.imageView[2] = (ImageView) view.findViewById(R.id.imageViewThumb2);
            holder.imageView[3] = (ImageView) view.findViewById(R.id.imageViewThumb3);
            holder.position = i;
            view.setTag(holder);

        }
        else{
            holder = (ViewHolder) view.getTag();
            holder.imageView[0].setImageBitmap(null);
            holder.imageView[1].setImageBitmap(null);
            holder.imageView[2].setImageBitmap(null);
            holder.imageView[3].setImageBitmap(null);

        }

        holder.name.setText(collection.getName());
        holder.date.setText(collection.getDate());
        holder.location.setText(collection.getLocation());
        holder.count.setText(String.valueOf(getImageCount((int) collection.getId())));
        new ThumbnailTask(i, holder).execute(imagePaths);

        //highlighten um active collection vorzuheben
        if( ((int)collection.getId()) == activeCollectionId){
            holder.active.setVisibility(View.VISIBLE);
            view.setBackgroundColor(context.getResources().getColor(R.color.bg_gray_highlight));
        }
        else{
            holder.active.setVisibility(View.INVISIBLE);
            view.setBackgroundColor(0x00000000);
        }

        return view;
    }
 
J

JustinTime

Fortgeschrittenes Mitglied
Und der Rest funktioniert nun?
 
C

CoffeeCode

Ambitioniertes Mitglied
hmm bei einigem hin und her scrollen kommen doch Fehler.

Ich vermute mal du stellst die Frage weil im Code etwas nicht stimmt oder falsch gelöst wurde?
 
Ähnliche Themen - AsyncTask im BaseAdapter läd Thumbbitmaps nicht wie gewünscht Antworten Datum
8