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();
}
}
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