mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-05-04 20:30:36 +00:00
Use glide to load and cache icons
This patch adds a dependency to glide to handle the loading and caching of icons. In my testing it eliminated the lag previously experienced in the main activity when quickly scrolling through a large list of entries. It does add an extra 1MB to the APK size, but I think that's acceptable for the amount of complexity it handles for us.
This commit is contained in:
parent
550e53f225
commit
9c5726cbca
8 changed files with 248 additions and 66 deletions
|
@ -4,11 +4,8 @@ import android.app.Activity;
|
|||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
|
@ -39,12 +36,14 @@ import com.beemdevelopment.aegis.otp.OtpInfo;
|
|||
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||
import com.beemdevelopment.aegis.otp.SteamInfo;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.text.Collator;
|
||||
|
@ -54,6 +53,8 @@ import java.util.TreeSet;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import androidx.annotation.ArrayRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
|
@ -135,9 +136,12 @@ public class EditEntryActivity extends AegisActivity {
|
|||
// fill the fields with values if possible
|
||||
if (_origEntry != null) {
|
||||
if (_origEntry.hasIcon()) {
|
||||
byte[] imageBytes = _origEntry.getIcon();
|
||||
Bitmap bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
|
||||
_iconView.setImageBitmap(bitmap);
|
||||
Glide.with(this)
|
||||
.asDrawable()
|
||||
.load(_origEntry)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false)
|
||||
.into(_iconView);
|
||||
_hasCustomIcon = true;
|
||||
} else {
|
||||
TextDrawable drawable = TextDrawableHelper.generate(_origEntry.getIssuer(), _origEntry.getName(), _iconView);
|
||||
|
@ -387,28 +391,33 @@ public class EditEntryActivity extends AegisActivity {
|
|||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, final int resultCode, Intent data) {
|
||||
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
|
||||
Uri inputFile = (data.getData());
|
||||
InputStream inputStream;
|
||||
Bitmap bitmap;
|
||||
try {
|
||||
inputStream = getContentResolver().openInputStream(inputFile);
|
||||
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
|
||||
bitmap = BitmapFactory.decodeStream(inputStream, null, bmOptions);
|
||||
_kropView.setBitmap(bitmap);
|
||||
_kropView.setVisibility(View.VISIBLE);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Glide.with(this)
|
||||
.asBitmap()
|
||||
.load(data.getData())
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false)
|
||||
.into(new CustomTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
||||
_kropView.setBitmap(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
|
||||
}
|
||||
});
|
||||
_iconView.setVisibility(View.GONE);
|
||||
_kropView.setVisibility(View.VISIBLE);
|
||||
|
||||
_saveImageButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
_iconView.setImageBitmap(_kropView.getCroppedBitmap());
|
||||
_iconView.setVisibility(View.VISIBLE);
|
||||
_kropView.setVisibility(View.GONE);
|
||||
_hasCustomIcon = true;
|
||||
_hasChangedIcon = true;
|
||||
|
@ -499,8 +508,9 @@ public class EditEntryActivity extends AegisActivity {
|
|||
|
||||
if (_hasChangedIcon) {
|
||||
if (_hasCustomIcon) {
|
||||
Bitmap bitmap = ((BitmapDrawable) _iconView.getDrawable()).getBitmap();
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
drawableToBitmap(_iconView.getDrawable()).compress(Bitmap.CompressFormat.JPEG, 100, stream);
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
|
||||
byte[] data = stream.toByteArray();
|
||||
entry.setIcon(data);
|
||||
} else {
|
||||
|
@ -560,27 +570,6 @@ public class EditEntryActivity extends AegisActivity {
|
|||
return -1;
|
||||
}
|
||||
|
||||
private static Bitmap drawableToBitmap(Drawable drawable) {
|
||||
if (drawable instanceof BitmapDrawable) {
|
||||
return ((BitmapDrawable) drawable).getBitmap();
|
||||
}
|
||||
|
||||
final int width = !drawable.getBounds().isEmpty() ? drawable
|
||||
.getBounds().width() : drawable.getIntrinsicWidth();
|
||||
|
||||
final int height = !drawable.getBounds().isEmpty() ? drawable
|
||||
.getBounds().height() : drawable.getIntrinsicHeight();
|
||||
|
||||
final Bitmap bitmap = Bitmap.createBitmap(width <= 0 ? 1 : width,
|
||||
height <= 0 ? 1 : height, Bitmap.Config.ARGB_8888);
|
||||
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private static DatabaseEntry cloneEntry(DatabaseEntry entry) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.beemdevelopment.aegis.ui.glide;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.Registry;
|
||||
import com.bumptech.glide.annotation.GlideModule;
|
||||
import com.bumptech.glide.module.AppGlideModule;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@GlideModule
|
||||
public class AegisGlideModule extends AppGlideModule {
|
||||
@Override
|
||||
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
|
||||
registry.prepend(DatabaseEntry.class, ByteBuffer.class, new IconLoader.Factory());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.beemdevelopment.aegis.ui.glide;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
import com.bumptech.glide.Priority;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
import com.bumptech.glide.load.Options;
|
||||
import com.bumptech.glide.load.data.DataFetcher;
|
||||
import com.bumptech.glide.load.model.ModelLoader;
|
||||
import com.bumptech.glide.load.model.ModelLoaderFactory;
|
||||
import com.bumptech.glide.load.model.MultiModelLoaderFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class IconLoader implements ModelLoader<DatabaseEntry, ByteBuffer> {
|
||||
@Override
|
||||
public LoadData<ByteBuffer> buildLoadData(@NonNull DatabaseEntry model, int width, int height, @NonNull Options options) {
|
||||
return new LoadData<>(new UUIDKey(model.getUUID()), new Fetcher(model));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handles(@NonNull DatabaseEntry model) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class Fetcher implements DataFetcher<ByteBuffer> {
|
||||
private DatabaseEntry _model;
|
||||
|
||||
private Fetcher(DatabaseEntry model) {
|
||||
_model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super ByteBuffer> callback) {
|
||||
byte[] bytes = _model.getIcon();
|
||||
ByteBuffer buf = ByteBuffer.wrap(bytes);
|
||||
callback.onDataReady(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Class<ByteBuffer> getDataClass() {
|
||||
return ByteBuffer.class;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DataSource getDataSource() {
|
||||
return DataSource.MEMORY_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements ModelLoaderFactory<DatabaseEntry, ByteBuffer> {
|
||||
@NonNull
|
||||
@Override
|
||||
public ModelLoader<DatabaseEntry, ByteBuffer> build(@NonNull MultiModelLoaderFactory unused) {
|
||||
return new IconLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.beemdevelopment.aegis.ui.glide;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.bumptech.glide.load.Key;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UUIDKey implements Key {
|
||||
private UUID _uuid;
|
||||
|
||||
public UUIDKey(UUID uuid) {
|
||||
_uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
|
||||
messageDigest.update(_uuid.toString().getBytes(CHARSET));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return _uuid.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return _uuid.hashCode();
|
||||
}
|
||||
}
|
|
@ -22,9 +22,9 @@ import java.util.UUID;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements ItemTouchHelperAdapter {
|
||||
private EntryListView _view;
|
||||
private List<DatabaseEntry> _entries;
|
||||
private List<DatabaseEntry> _shownEntries;
|
||||
private static Listener _listener;
|
||||
private boolean _showAccountName;
|
||||
private boolean _tapToReveal;
|
||||
private int _tapToRevealTime;
|
||||
|
@ -37,11 +37,11 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
// keeps track of the viewholders that are currently bound
|
||||
private List<EntryHolder> _holders;
|
||||
|
||||
public EntryAdapter(Listener listener) {
|
||||
public EntryAdapter(EntryListView view) {
|
||||
_entries = new ArrayList<>();
|
||||
_shownEntries = new ArrayList<>();
|
||||
_holders = new ArrayList<>();
|
||||
_listener = listener;
|
||||
_view = view;
|
||||
}
|
||||
|
||||
public void setShowAccountName(boolean showAccountName) {
|
||||
|
@ -56,6 +56,10 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
_tapToRevealTime = number;
|
||||
}
|
||||
|
||||
public DatabaseEntry getEntryAt(int position) {
|
||||
return _shownEntries.get(position);
|
||||
}
|
||||
|
||||
public void addEntry(DatabaseEntry entry) {
|
||||
_entries.add(entry);
|
||||
if (isEntryFiltered(entry)) {
|
||||
|
@ -232,7 +236,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
return;
|
||||
}
|
||||
|
||||
_listener.onEntryDrop(_shownEntries.get(position));
|
||||
_view.onEntryDrop(_shownEntries.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -243,7 +247,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
}
|
||||
|
||||
// notify the database first
|
||||
_listener.onEntryMove(_entries.get(firstPosition), _entries.get(secondPosition));
|
||||
_view.onEntryMove(_entries.get(firstPosition), _entries.get(secondPosition));
|
||||
|
||||
// update our side of things
|
||||
Collections.swap(_entries, firstPosition, secondPosition);
|
||||
|
@ -260,7 +264,9 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
public EntryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
View view = inflater.inflate(_viewMode.getLayoutId(), parent, false);
|
||||
return new EntryHolder(view);
|
||||
EntryHolder holder = new EntryHolder(view);
|
||||
_view.setPreloadView(holder.getIconView());
|
||||
return holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -275,6 +281,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
boolean showProgress = !isPeriodUniform() && entry.getInfo() instanceof TotpInfo;
|
||||
holder.setData(entry, _showAccountName, showProgress, _tapToReveal);
|
||||
holder.setTapToRevealTime(_tapToRevealTime);
|
||||
holder.loadIcon(_view);
|
||||
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -283,7 +290,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
if (_tapToReveal && holder.isCodeHidden()) {
|
||||
holder.revealCode();
|
||||
} else {
|
||||
_listener.onEntryClick(_shownEntries.get(position));
|
||||
_view.onEntryClick(_shownEntries.get(position));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -291,7 +298,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
int position = holder.getAdapterPosition();
|
||||
return _listener.onLongEntryClick(_shownEntries.get(position));
|
||||
return _view.onLongEntryClick(_shownEntries.get(position));
|
||||
}
|
||||
});
|
||||
holder.setOnRefreshClickListener(new View.OnClickListener() {
|
||||
|
@ -306,7 +313,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
|
||||
// notify the listener that the counter has been incremented
|
||||
// this gives it a chance to save the database
|
||||
_listener.onEntryChange(entry);
|
||||
_view.onEntryChange(entry);
|
||||
|
||||
// finally, refresh the code in the UI
|
||||
holder.refreshCode();
|
||||
|
@ -331,7 +338,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
|
|||
holder.setShowProgress(!_isPeriodUniform);
|
||||
}
|
||||
|
||||
_listener.onPeriodUniformityChanged(_isPeriodUniform);
|
||||
_view.onPeriodUniformityChanged(_isPeriodUniform);
|
||||
}
|
||||
|
||||
public int getUniformPeriod() {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.beemdevelopment.aegis.ui.views;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
|
@ -17,7 +15,10 @@ import com.beemdevelopment.aegis.otp.HotpInfo;
|
|||
import com.beemdevelopment.aegis.otp.OtpInfo;
|
||||
import com.beemdevelopment.aegis.otp.SteamInfo;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class EntryHolder extends RecyclerView.ViewHolder {
|
||||
|
@ -84,15 +85,6 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
_profileName.setText(" - " + entry.getName());
|
||||
}
|
||||
|
||||
if (_entry.hasIcon()) {
|
||||
byte[] imageBytes = entry.getIcon();
|
||||
Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
|
||||
_profileDrawable.setImageBitmap(image);
|
||||
} else {
|
||||
TextDrawable drawable = TextDrawableHelper.generate(entry.getIssuer(), entry.getName(), _profileDrawable);
|
||||
_profileDrawable.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
// cancel any scheduled hideCode calls
|
||||
_hiddenHandler.removeCallbacksAndMessages(null);
|
||||
|
||||
|
@ -103,6 +95,24 @@ public class EntryHolder extends RecyclerView.ViewHolder {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadIcon(Fragment fragment) {
|
||||
if (_entry.hasIcon()) {
|
||||
Glide.with(fragment)
|
||||
.asDrawable()
|
||||
.load(_entry)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false)
|
||||
.into(_profileDrawable);
|
||||
} else {
|
||||
TextDrawable drawable = TextDrawableHelper.generate(_entry.getIssuer(), _entry.getName(), _profileDrawable);
|
||||
_profileDrawable.setImageDrawable(drawable);
|
||||
}
|
||||
}
|
||||
|
||||
public ImageView getIconView() {
|
||||
return _profileDrawable;
|
||||
}
|
||||
|
||||
public void setTapToRevealTime(int number) {
|
||||
_tapToRevealTime = number;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,18 @@ import com.beemdevelopment.aegis.db.DatabaseEntry;
|
|||
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
|
||||
import com.beemdevelopment.aegis.helpers.UiRefresher;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.ListPreloader;
|
||||
import com.bumptech.glide.RequestBuilder;
|
||||
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.util.ViewPreloadSizeProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
|
@ -34,6 +42,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
|
||||
private RecyclerView _recyclerView;
|
||||
private RecyclerView.ItemDecoration _dividerDecoration;
|
||||
private ViewPreloadSizeProvider<DatabaseEntry> _preloadSizeProvider;
|
||||
private PeriodProgressBar _progressBar;
|
||||
private boolean _showProgress;
|
||||
private ViewMode _viewMode;
|
||||
|
@ -61,8 +70,14 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
}
|
||||
});
|
||||
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(view.getContext());
|
||||
_recyclerView.setLayoutManager(mLayoutManager);
|
||||
// set up icon preloading
|
||||
_preloadSizeProvider = new ViewPreloadSizeProvider<>();
|
||||
IconPreloadProvider modelProvider = new IconPreloadProvider();
|
||||
RecyclerViewPreloader<DatabaseEntry> preloader = new RecyclerViewPreloader<>(Glide.with(this), modelProvider, _preloadSizeProvider, 10);
|
||||
_recyclerView.addOnScrollListener(preloader);
|
||||
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(view.getContext());
|
||||
_recyclerView.setLayoutManager(layoutManager);
|
||||
_touchCallback = new SimpleItemTouchHelperCallback(_adapter);
|
||||
ItemTouchHelper touchHelper = new ItemTouchHelper(_touchCallback);
|
||||
touchHelper.attachToRecyclerView(_recyclerView);
|
||||
|
@ -87,6 +102,10 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
return view;
|
||||
}
|
||||
|
||||
public void setPreloadView(View view) {
|
||||
_preloadSizeProvider.setView(view);
|
||||
}
|
||||
|
||||
public void setGroupFilter(String group, boolean apply) {
|
||||
_touchCallback.setIsLongPressDragEnabled(group == null);
|
||||
_adapter.setGroupFilter(group, apply);
|
||||
|
@ -253,4 +272,26 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
|
|||
outRect.bottom = _height;
|
||||
}
|
||||
}
|
||||
|
||||
private class IconPreloadProvider implements ListPreloader.PreloadModelProvider<DatabaseEntry> {
|
||||
@NonNull
|
||||
@Override
|
||||
public List<DatabaseEntry> getPreloadItems(int position) {
|
||||
DatabaseEntry entry = _adapter.getEntryAt(position);
|
||||
if (!entry.hasIcon()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(entry);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RequestBuilder getPreloadRequestBuilder(@NonNull DatabaseEntry entry) {
|
||||
return Glide.with(EntryListView.this)
|
||||
.asDrawable()
|
||||
.load(entry)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue