2016-07-17 21 views
1

Ich habe an einer App gearbeitet, die Thumbnails und Text von Parse herunterlädt und sie zu ArrayLists hinzufügt, die dann über einen benutzerdefinierten Adapter für eine ListView angezeigt werden. Das Problem hier ist, die Thumbnails für den erforderlichen Inhalt sind manchmal fehlplatziert. Zum Beispiel: In meinem Profil wird anstelle meines Bildes ein Bild eingefügt, das von Parse heruntergeladen wurde. Wie man es repariert ?Das Herunterladen von Bildern und Text aus Parse und Hinzufügen zu ArrayList liefert ein unerwartetes Ergebnis?

MainActivity.java (Downloads den Inhalt)

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

if (isParseInitialized == false) { 

     Parse.initialize(new Parse.Configuration.Builder(this) 
         .applicationId("AppId") 
       .clientKey("ClientKey") 
       .server("https://parseapi.back4app.com") 

       .build() 
     ); 

     isParseInitialized = true; 

    } 

    catchVideos(); 

    progressBar = (ProgressBar) findViewById(R.id.progressBar); 

    context = this; 
    listView = (ListView) findViewById(R.id.listView); 

    customAdapter = new CustomAdapter(MainActivity.this, titles, thumbnails, channel); 

    //progressBar.setVisibility(View.INVISIBLE); 

    final Handler handler = new Handler(); 
    Runnable run = new Runnable() { 
     @Override 
     public void run() { 

      handler.postDelayed(this, 1000); 

      if (tapped == true) { 

       ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Content"); 
       query.whereEqualTo("Title", title); 
       query.findInBackground(new FindCallback<ParseObject>() { 
        @Override 
        public void done(List<ParseObject> objects, ParseException e) { 
         if(e == null) { 

          for (ParseObject object : objects) { 

           Log.i("Info", object.getString("url")); 

           Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(object.getString("url"))); 
           startActivity(intent); 
          } 
         } 
        } 
       }); 

       tapped = false; 

      } 
     } 
    }; 

    handler.post(run); 



} 

public void catchVideos(){ 

    ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("Content"); 
    query.whereNotEqualTo("Status", null); 
    query.orderByDescending("createdAt"); 
    query.findInBackground(new FindCallback<ParseObject>() { 
     @Override 
     public void done(List<ParseObject> objects, ParseException e) { 
      if(e == null) { 

       if (!titles.isEmpty()) { 
        titles.clear(); 
       } 

       if (!channel.isEmpty()) { 
        channel.clear(); 
       } 

       if (!thumbnails.isEmpty()) { 
        thumbnails.clear(); 
       } 

       for (ParseObject object : objects) { 

        titles.add(object.getString("Title")); 
        channel.add(object.getString("Channel")); 

        ParseFile file = (ParseFile) object.get("Thumbnail"); 
        file.getDataInBackground(new GetDataCallback() { 
         @Override 
         public void done(byte[] data, ParseException e) { 

          if (e == null) { 

           Bitmap thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length); 
           thumbnails.add(thumbnail); 

           listView.setAdapter(customAdapter); 

           progressBar.setVisibility(View.INVISIBLE); 

          } 

         } 
        }); 

        customAdapter.notifyDataSetChanged(); 

        Log.i("Info", object.getString("Title")); 
        Log.i("Info", object.getString("url")); 
       } 

      } 
     } 
    }); 
} 

CustomAdapter.java

 public class CustomAdapter extends BaseAdapter{ 

ArrayList<String> result; 
ArrayList<String> channelName; 
Context context; 
ArrayList<Bitmap> imageId; 
private static LayoutInflater inflater=null; 
public CustomAdapter(MainActivity mainActivity, ArrayList<String> titles, ArrayList<Bitmap> thumbnails, ArrayList<String> channel) { 
    // TODO Auto-generated constructor stub 
    result=titles; 
    channelName=channel; 
    context=mainActivity; 
    imageId=thumbnails; 
    inflater = (LayoutInflater)context. 
      getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 
@Override 
public int getCount() { 
    // TODO Auto-generated method stub 
    return result.size(); 
} 

@Override 
public Object getItem(int position) { 
    // TODO Auto-generated method stub 
    return position; 
} 

@Override 
public long getItemId(int position) { 
    // TODO Auto-generated method stub 
    return position; 
} 

public class Holder 
{ 
    TextView tv; 
    TextView channelText; 
    ImageView img; 
} 
@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    // TODO Auto-generated method stub 
    Holder holder=new Holder(); 
    View rowView; 
    rowView = inflater.inflate(R.layout.custom_row, null); 
    holder.tv=(TextView) rowView.findViewById(R.id.textView1); 
    holder.channelText = (TextView) rowView.findViewById(R.id.channel); 
    holder.img=(ImageView) rowView.findViewById(R.id.imageView1); 
    try { 
     holder.img.setImageBitmap(imageId.get(position)); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    holder.tv.setText(result.get(position)); 
    holder.channelText.setText(channelName.get(position)); 

    rowView.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      //Toast.makeText(context, "You Clicked "+ result.get(position), Toast.LENGTH_LONG).show(); 
      //Launch URL 
      MainActivity.tapped = true; 
      MainActivity.title = result.get(position); 

     } 
    }); 

    return rowView; 

    } 

    } 
+2

Bitte erläutern Sie, was Sie mit „die erforderliche Inhalt ist manchmal verlegt ". Wenn Sie das Problem nicht richtig erklären, kann niemand helfen. – Sufian

Antwort

0

Du fügst jedes Bild auf eine Liste, sobald es heruntergeladen wird. Später wiederholst du die Bilder der Reihe nach. Die Reihenfolge, in der sie in der Liste angezeigt werden, stimmt jedoch nicht unbedingt mit der Reihenfolge überein, in der Sie sie angefordert haben. Sie werden asynchron geladen, was bedeutet, dass der Code nicht auf das Laden des Bildes wartet, bevor er zum nächsten übergeht. Wenn Sie beginnen, ein großes Bild zu laden und sofort danach ein kleines Bild zu laden, könnte das kleine Bild zuerst heruntergeladen werden. In der resultierenden Liste würde das kleine Bild vor dem größeren erscheinen, obwohl es als zweites angefordert wurde.

Um die Reihenfolge der Liste der Bilder zu korrigieren, können Sie Futures verwenden. Anstatt thumbnails als List<Bitmap> zu deklarieren, machen Sie eine List<Future<Bitmap>>. Fügen Sie dann alle drei Elemente gleichzeitig zur Liste hinzu.

titles.add(object.getString("Title")); 
    channel.add(object.getString("Channel")); 
    CompletableFuture<Bitmap> futureThumbnail = new CompletableFuture<>(); 
    thumbnails.add(futureThumbnail); 

, dass alle drei Listen garantiert werden in der gleichen Reihenfolge, unabhängig davon, wie lange die Bilder downloaden dauern.

Der nächste Schritt ist, jede Zukunft mit dem entsprechenden Bild zu füllen.

ParseFile file = (ParseFile) object.get("Thumbnail"); 
    file.getDataInBackground(new GetDataCallback() { 
     @Override 
     public void done(byte[] data, ParseException e) { 
      if (e == null) { 
       Bitmap thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length); 
       future.complete(thumbnail); 
       ... 

Dieses Verfahren hat den zusätzlichen Vorteil, dass Sie warten können für die Bilder heruntergeladen zu beenden. So warten Sie auf alle Bilder herunterladen und sie in einer Liste in die richtige Reihenfolge gebracht:

List<Bitmap> thumbnails = new ArrayList<>(); 
for (Future<Bitmap> future : futureThumbnails) { 
    thumbnails.add(future.get()); 
} 

Oder, wenn Sie nicht lieber warten:

List<Bitmap> thumbnails = new ArrayList<>(); 
Bitmap defaultValue = null; // or preferably some other default value 
for (Future<Bitmap> future : futureThumbnails) { 
    thumbnails.add(future.isDone() ? future.get() : defaultValue); 
} 
+0

Es gibt ein Problem mit dem Code, für den ich denke (Future future: futureThumbnails) { thumbnails.add (future.get()); } - Kann nicht durchlaufen, und ich bekomme diesen Fehler Fehler: (202, 54) Fehler: for-each nicht für Ausdruckstyp erforderlich: Array oder java.lang.Iterable gefunden: CompletableFuture