0

ein wenig Hintergrund ...Android RecyclerView Persistent Bilder nach Async Herunterladen

Ich habe eine App, entworfen MVP verwenden, die Bilder und Text als Karte innerhalb eines RecyclerView anzeigt. Beim Öffnen der App werden API-Informationen abgerufen, die die Image-Download-URL enthalten. In meinem <RecyclerView.ViewHolder> Adapter. Ich führe eine AsyncTask aus, um das Bild für jede Karte herunterzuladen, wenn es erstellt wird, jeder Bilddownload (oder Karte) hat seinen eigenen Thread. Während des Downloads wird ein leeres graues Quadrat als Platzhalter angezeigt. All dies funktioniert bestimmt wie aber ...

das Problem ist ...

Während all dies funktioniert Ich habe bemerkt, dass, wenn ich (oder unten) und neue Kartenansichten scrollen erstellt werden Die Bilder werden erneut heruntergeladen. Ist es möglich, dass die Bilder nach dem Herunterladen nicht erneut heruntergeladen werden müssen, wenn dieselbe Karte (oder ihr Index) neu erstellt wird. Dies kann in Play Kiosk und Instagram Apps oder jede App, die eine Liste von Bildern enthält, gesehen werden.

Wie kann ich dies in meiner App erreichen?

mögliche Lösungen ...

I) alle Bilder Download (und nicht nur die URLs) vor und während der Zeit der RecyclerView erstellt wird eine ThreadPoolExecutor verwenden und diese in unsere <RecyclerView.ViewHolder> Adapter passieren.

II) Verwenden Sie das ViewHolder Muster. Beim Binden des ImageView innerhalb meines Adapters würde es auf ein Objekt im Presenter/Model-Layer verweisen, das ein gespeichertes Bild bereitstellen oder eines herunterladen würde, wenn kein Bild verfügbar ist.

III) In eine Art von Logik vor der Bindung wie

if(image has already been download) { 
    getDownloadedImage() 
} else { 
    downloadNewImage() 
} 

Ratschläge oder drückt in der richtigen Richtung wäre sehr dankbar!

Bitte lassen Sie mich wissen, wenn Sie weitere Informationen oder Code benötigen.

der Code ...

NewsAdapter

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 

    switch (holder.getItemViewType()) { 
     case IMAGE_LAYOUT: 
      ImageViewHolder imageViewHolder = (ImageViewHolder) holder; 
      initViewholderImage(imageViewHolder, position); 
      break; 

     default: 
      break; 
    } 

} 

private void initViewholderImage(ImageViewHolder holder, int position) { 
    holder.titleText.setText(articleList.get(position).getTitle()); 
    holder.abstractText.setText(articleList.get(position).getAbstract()); 
    holder.globalText.setText(articleList.get(position).getGeoFacet().get(0)); 

    try { 
//this is where we are downloading our image in a background thread 
    ImageDownload imageDownloader = new ImageDownloader(); 
     imageDownloader.imageDownload(articleList.get(position).getMultimedia().get(3).getUrl(), 
       holder.articleImage); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 
} 

ImageDownloader

public class ImageDownloader { 
private final String TAG = getClass().getSimpleName(); 

public ImageDownloader() { 

} 

public void imageDownload(String url, ImageView imageView) { 

    if(cancelPotentialDownload(url, imageView)) { 
     BitmapDownloaderAsyncTask asyncTask = new BitmapDownloaderAsyncTask(imageView); 
     DownloadDrawable downloadDrawable = new DownloadDrawable(asyncTask); 
     imageView.setImageDrawable(downloadDrawable); 
     asyncTask.execute(url); 
    } 
} 

private static BitmapDownloaderAsyncTask getBitmapDownloaderTask(ImageView imageView) { 
    if (imageView != null) { 
     Drawable drawable = imageView.getDrawable(); 
     if (drawable instanceof DownloadDrawable) { 
      DownloadDrawable downloadedDrawable = (DownloadDrawable)drawable; 
      return downloadedDrawable.getBitmapDownloadTask(); 
     } 
    } 
    return null; 
} 

private static boolean cancelPotentialDownload(String url, ImageView imageView) { 
    BitmapDownloaderAsyncTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView); 

    if (bitmapDownloaderTask != null) { 
     String bitmapUrl = bitmapDownloaderTask.url; 
     if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) { 
      bitmapDownloaderTask.cancel(true); 
     } else { 
      // The same URL is already being downloaded. 
      return false; 
     } 
    } 
    return true; 
} 

class BitmapDownloaderAsyncTask extends AsyncTask<String, Void, Bitmap> { 

    private String url; 
    private final WeakReference<ImageView> weakImageView; 

    public BitmapDownloaderAsyncTask(ImageView imageView) { 
     weakImageView = new WeakReference<ImageView>(imageView); 
    } 

    @Override 
    protected Bitmap doInBackground(String... params) { 

     return ImageHelper.getBitmapFromURL(params[0]); //parameters are given in an array 
    } 

    @Override 
    protected void onPostExecute(Bitmap bitmap) { 
     if (isCancelled()) { 
      bitmap = null; 
     } 

     if (weakImageView != null) { 
      ImageView imageView = weakImageView.get(); 
      if (imageView != null) { 
       imageView.setImageBitmap(bitmap); 

       /*int bgColor = Palette.from(bitmap).generate().getDarkVibrantColor(
         ContextCompat.getColor(App.getAppComponent().getApplicationContext(), android.R.color.black)); 

       bgLayout.setBackgroundColor(bgColor);*/ 
      } 
     } 
    } 
} 

static class DownloadDrawable extends ColorDrawable { //can we change this to a Bitmap Drawable 
    private final WeakReference<BitmapDownloaderAsyncTask> weakBitmapAsyncTask; 

    public DownloadDrawable(BitmapDownloaderAsyncTask task) { 
     super(Color.LTGRAY); 
     weakBitmapAsyncTask = new WeakReference<BitmapDownloaderAsyncTask>(task); 
    } 

    public BitmapDownloaderAsyncTask getBitmapDownloadTask() { 
     return weakBitmapAsyncTask.get(); 
    } 
} 

}

NewsActivity

public class NewsActivity extends BaseActivity implements NewsView{ 
private final String TAG = getClass().getSimpleName(); 

private static NewsPresenterComponent newsPresenterComponent; 

@Inject NewsPresenter presenter; 

RecyclerView recyclerView; 
NewsAdapter adapter; 

List<Article> articles; 


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

    implementComponents(); 

    articles = presenter.queryNews("world", 20); 

    initializeRecyclerView(); 

} 

public void implementComponents() { 
    newsPresenterComponent = DaggerNewsPresenterComponent.builder() 
      .newsPresenterModule(new NewsPresenterModule(this, this)) //this can be removed 
      .build(); 
    newsPresenterComponent.inject(this); 
} 

private void initializeRecyclerView() { 
    recyclerView = (RecyclerView) findViewById(R.id.list); 
    final LinearLayoutManager layoutManager = new LinearLayoutManager(this); 
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL); 
    recyclerView.setLayoutManager(layoutManager); 

    adapter = new NewsAdapter(this, articles); 
    recyclerView.setAdapter(adapter); 
} 

@Override 
public void updateNewsAdapter() { 
    adapter.notifyDataSetChanged(); 
} 

}

+0

Sie müssen die Bilder zwischenspeichern (z. B. in den internen/externen Speicher schreiben). Dann überprüfe ob es existiert -> lies es von dort, ansonsten lade es herunter – Nikola

Antwort

0

Gerade Picasso verwenden, das Caching, Platzhalter Bild und viele andere Dinge an gebaut hat. Sie können Ihre gesamte Klasse durch nur eine Zeile ersetzen.