I am trying to load a custom model into Glide but getting this error:
GlideExecutor: Request threw uncaught throwable
com.bumptech.glide.Registry$NoModelLoaderAvailableException: Failed to
find any ModelLoaders for model:
com.company.project.glide.Movie#aac331a
Glide Version: 4.0.0
My codes:
Model
public class Movie {
private String name;
private String artist;
public Movie(String name, String artist) {
this.name = name;
this.artist = artist;
}
public String getName() {
return name;
}
public String getArtist() {
return artist;
}
}
Module
#com.bumptech.glide.annotation.GlideModule
public class GlideModule extends AppGlideModule {
#Override
public boolean isManifestParsingEnabled() {
return false;
}
#Override
public void applyOptions(Context context, GlideBuilder builder) {
super.applyOptions(context, builder);
}
#Override
public void registerComponents(Context context, Registry registry) {
registry.append(Movie.class, InputStream.class, new MovieArtModel.Factory());
}
}
ModelLoader
public class MovieArtModel implements ModelLoader<Movie, InputStream> {
#Nullable
#Override
public LoadData<InputStream> buildLoadData(Movie movie, int width, int height, Options options) {
Timber.d("buildLoadData: ");
return new LoadData<>(new ObjectKey(movie), new MovieArtLoader(movie, width, height));
}
#Override
public boolean handles(Movie movie) {
return false;
}
public static class Factory implements ModelLoaderFactory<Movie, InputStream> {
#Override
public ModelLoader<Movie, InputStream> build(MultiModelLoaderFactory multiFactory) {
return new MovieArtModel();
}
#Override
public void teardown() {
}
}
static class MovieArtLoader implements DataFetcher<InputStream> {
private Movie movie;
private boolean isCancelled = false;
private int widthSize;
private int heightSize;
MovieArtLoader(Movie movie, int widthSize, int heightSize) {
Timber.d("MovieArtLoader: Initializing...width size = " + widthSize + " :: heightSize = " + heightSize);
this.movie = movie;
this.widthSize = widthSize;
this.heightSize = heightSize;
}
#Override
public void loadData(Priority priority, DataCallback<? super InputStream> callback) {
Timber.d("loadData");
//First check if request is not cancelled before starting request
if(!isCancelled()) {
InputStream inputStream = getMovieArtInputStream(movie);
if (inputStream != null) {
callback.onDataReady(inputStream);
} else {
callback.onLoadFailed(new IOException("Forced Glide network failure. Can't load Movie image"));
}
}
}
return null;
}
#Override public void cleanup() {
Timber.d("cleanup: ");
}
#Override public void cancel() {
Timber.d("cancel: ");
isCancelled = true;
}
#Override
public Class<InputStream> getDataClass() {
return null;
}
#Override
public DataSource getDataSource() {
return null;
}
private boolean isCancelled() {
return isCancelled;
}
}
Then I am loading it thus:
GlideApp.with(itemView.getContext())
.asBitmap()
.load(new Movie(book.getMovieName(), book.getArtist()))
.placeholder(R.drawable.movie_default_small)
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.listener(this)
.into(imageView);
Please where am I getting it wrong?
EDIT
I applied the answer below but I began to get NPE. This is the stacktrace:
E/GlideExecutor: Request threw uncaught throwable
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference
at com.bumptech.glide.util.MultiClassKey.hashCode(MultiClassKey.java:66)
at android.support.v4.util.SimpleArrayMap.indexOfKey(SimpleArrayMap.java:320)
at android.support.v4.util.SimpleArrayMap.get(SimpleArrayMap.java:360)
at com.bumptech.glide.provider.LoadPathCache.get(LoadPathCache.java:34)
at com.bumptech.glide.Registry.getLoadPath(Registry.java:132)
at com.bumptech.glide.load.engine.DecodeHelper.getLoadPath(DecodeHelper.java:132)
at com.bumptech.glide.load.engine.DecodeHelper.hasLoadPath(DecodeHelper.java:128)
at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:59)
at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:282)
at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:252)
at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:222)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:347)
#Override
public boolean handles(Movie movie) {
return true;
}
You need to do this or else Glide will ignore your ModelLoader, thinking it does not handle the provided Movie model.
NoModelLoaderAvailableException happened when no
{#linkcom.bumptech.glide.load.model.ModelLoader} is registered for a given
model class, and that fixed with #talkLittle answer, and plus on that Movie should implement equals() and hashCode() to get caching to work correctly.
The new NPE happened because you accepted #Nullable would try #NonNull annotation.
Check .load and .into:
Glide.with(this)
.load(check_here)
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.NONE))
.into(new DrawableImageViewTarget(check_here));
Related
i know actually a lot of these kinds of questions, and i have searched on google but i can't find where the error is in my code.
I tried to send a request to fetch data, but it runs the onFailure method which reads "NumberFormatException: Empty string" and the data can't be displayed in the recyclerview, even though I'm also getting a json response as I wanted.
i got this response:
{
"kode":1,
"pesan":"Barang ditemukan",
"data":[
{
"Sat_1":"PT",
"Sat_2":"",
"Isi_2":"",
"KdBrg":"280349191",
"NmBrg":"SILICONE PACIFIER STEP 1A",
"Stock_Akhir":"0",
"Hrg":28000
}
]
}
my object model
public class ModelDataBarang {
private int Isi_2;
private int Isi_3;
private int Isi_4;
private String KdBrg;
private String NmBrg;
private String Sat_1;
private String Sat_2;
private String Sat_3;
private String Sat_4;
private String KdHrgList;
private double Stock_Akhir;
private double HrgJl11;
public double getHrgJl11() {
return HrgJl11;
}
public void setHrgJl11(double hrgJl11) {
HrgJl11 = hrgJl11;
}
private String Hrg;
public String getHrg() {
return Hrg;
}
public void setHrg(String hrg) {
Hrg = hrg;
}
public String getKdHrgList() {
return KdHrgList;
}
public void setKdHrgList(String kdHrgList) {
KdHrgList = kdHrgList;
}
public String getSat_3() {
return this.Sat_3;
}
public void setSat_3(String sat_3) {
this.Sat_3 = sat_3;
}
public String getSat_4() {
return this.Sat_4;
}
public void setSat_4(String sat_4) {
this.Sat_4 = sat_4;
}
public int getIsi_3() {
return this.Isi_3;
}
public void setIsi_3(int isi_3) {
this.Isi_3 = isi_3;
}
public int getIsi_4() {
return this.Isi_4;
}
public void setIsi_4(int isi_4) {
this.Isi_4 = isi_4;
}
public String getKdBrg() {
return this.KdBrg;
}
public void setKdBrg(String kdBrg) {
this.KdBrg = kdBrg;
}
public String getNmBrg() {
return this.NmBrg;
}
public void setNmBrg(String nmBrg) {
this.NmBrg = nmBrg;
}
public String getSat_1() {
return this.Sat_1;
}
public void setSat_1(String sat_1) {
this.Sat_1 = sat_1;
}
public String getSat_2() {
return this.Sat_2;
}
public void setSat_2(String sat_2) {
this.Sat_2 = sat_2;
}
public int getIsi_2() {
return this.Isi_2;
}
public void setIsi_2(int isi_2) {
this.Isi_2 = isi_2;
}
public double getStock_Akhir() {
return this.Stock_Akhir;
}
public void setStock_Akhir(double stock_Akhir) {
this.Stock_Akhir = stock_Akhir;
}
public String toString() {
return this.NmBrg;
}
}
my recyclerview data holder
ModelDataBarang modelBarangResto= listModel.get(position);
holder.tvKdBrg.setText(modelBarangResto.getKdBrg());
holder.tvNmBarang.setText(modelBarangResto.getNmBrg());
holder.tvHrgBrg.setText(String.valueOf(modelBarangResto.getHrg()));
all answers i will appreciate
Your model class values are not defined as per your response. Try to check and modify respective return type. You are getting this error because you have defined Isi_2 as int in your model class but in response you are getting empty string.
Replace this
private int Isi_2;
With this
private String Isi_2;
Trying to learn Room and RXJAVA.
I have about 80% of this understood but I'm getting stuck on figuring the rest out.
Here is the error I get on the insert data.
java.lang.NullPointerException: Attempt to invoke interface method
'void
com.example.learnroom.EntityDao.insert(com.example.learnroom.Entitys)'
on a null object reference
If I don't run the try catch I get the following error which seems to be related.
java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example.learnroom/com.example.learnroom.MainActivity}:
java.lang.NullPointerException: Attempt to invoke interface method
'io.reactivex.Maybe
com.example.learnroom.EntityDao.getEntity(java.lang.String)' on a null
object reference
How do I fix this?
I have tried to simplify from the tutorials all over the web most using recyclerviews to just 2 text fields. They say this is 3 pieces but it doesn't seem like it, as the DB was never set up so I ran it in a method to run the code. Maybe someone can help explain to me how this really works.
my code
Dao
public interface EntityDao {
#Query("SELECT * FROM Entitys WHERE ID = :ID LIMIT 1")
Maybe<List<Entitys>> getEntity(String ID);
#Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(Entitys entitys);
#Query("DELETE FROM Entitys")
void deleteAllEntity();
}
Entity
public class Entitys {
#PrimaryKey
#NonNull
public String ID;
public String ts;
public String tss;
public Entitys(#NonNull String ID, String ts, String tss) {
this.ID = ID;
this.ts = ts;
this.tss = tss;
}
public String getTss() {
return tss;
}
public void setTss(String tss) {
this.tss = tss;
}
public void setID(String ID) {
this.ID = ID;
}
public void setTs(String ts) {
this.ts = ts;
}
public String getID() {
return ID;
}
public String getTs() {
return ts;
}
}
database
#Database(entities = {Entitys.class}, version = 1)
public abstract class PathwaysDB extends RoomDatabase {
private static volatile PathwaysDB INSTANCE;
public static EntityDao entityDao() {
return null;
}
public static PathwaysDB getInstance(Context context) {
if (INSTANCE == null) {
synchronized (PathwaysDB.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
PathwaysDB.class, "Pathwaysdb")
.build();
}
}
}
return INSTANCE;
}
}
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = MainActivity.class.getSimpleName();
Button tb;
EditText te, tes;
String ts, tss, ID;
CompositeDisposable compositeDisposable = new CompositeDisposable();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ID ="test";
te = findViewById(R.id.te);
tb = findViewById(R.id.tb);
tb.setOnClickListener(this);
tes = findViewById(R.id.tes);
Builddb();
try{
getData();}catch (Exception e){}
}
private void Builddb() {
Completable.fromAction(() -> PathwaysDB.getInstance(this))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
#Override
public void onComplete() {
// action was completed successfully
}
#Override
public void onError(Throwable e) {
// something went wrong
}
});
}
private void getData() {
Maybe<List<Entitys>> single = entityDao().getEntity(ID);
single.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new MaybeObserver<List<Entitys>>() {
#Override
public void onSubscribe(Disposable d) {
// add it to a CompositeDisposable
}
#Override
public void onSuccess(List<Entitys> entity) {
te.setText(entity.indexOf(ts));
tes.setText(entity.indexOf(tss));
}
#Override
public void onError(Throwable e) {
// show an error message
}
#Override
public void onComplete() {
}
});
compositeDisposable.add((Disposable) single);
}
#Override
protected void onDestroy() {
super.onDestroy();
compositeDisposable.dispose();
}
private void updateUserName() {
ts = te.getText().toString();
tss = tes.getText().toString();
Entitys entitys = new Entitys(ID, ts, tss);
Completable.fromAction(() -> entityDao().insert(entitys))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
#Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
#Override
public void onComplete() {
// action was completed successfully
}
#Override
public void onError(Throwable e) {
// something went wrong
}
});
}
#Override
public void onClick(View view) {
updateUserName();
Intent forward = new Intent(this, secondpage.class);
startActivity(forward);
}
}
Reason for crash is this line in your PathwaysDB class
public static EntityDao entityDao() {
return null;
}
it is returning null. It should be like
public abstract EntityDao entityDao()
You forget to add #Dao annonation to your EntityDao interface class.
also you need to change below method :
public static EntityDao entityDao() {
return null;
}
To
public abstract EntityDao entityDao();
I am making an Android TV app. I want to load images from URLs into BackgroundManager drawables using Picasso.
In Glide, it is done using the following code:
Glide.with(getActivity())
.load(uri)
.centerCrop()
.error(mDefaultBackground)
.into(new SimpleTarget<GlideDrawable>(width, height) {
#Override
public void onResourceReady(GlideDrawable resource,
GlideAnimation<? super GlideDrawable> glideAnimation) {
mBackgroundManager.setDrawable(resource);
}
});
How do I do the same using Picasso?
here is solution i found.
public class PicassoBackgroundManager {
private static final String TAG = PicassoBackgroundManager.class.getSimpleName();
private static int BACKGROUND_UPDATE_DELAY = 500;
private final int DEFAULT_BACKGROUND_RES_ID = R.drawable.default_background;
private static Drawable mDefaultBackground;
// Handler attached with main thread
private final Handler mHandler = new Handler(Looper.getMainLooper());
private Activity mActivity;
private BackgroundManager mBackgroundManager = null;
private DisplayMetrics mMetrics;
private URI mBackgroundURI;
private PicassoBackgroundManagerTarget mBackgroundTarget;
Timer mBackgroundTimer; // null when no UpdateBackgroundTask is running.
public PicassoBackgroundManager (Activity activity) {
mActivity = activity;
mDefaultBackground = activity.getDrawable(DEFAULT_BACKGROUND_RES_ID);
mBackgroundManager = BackgroundManager.getInstance(activity);
mBackgroundManager.attach(activity.getWindow());
mBackgroundTarget = new PicassoBackgroundManagerTarget(mBackgroundManager);
mMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
}
/**
* if UpdateBackgroundTask is already running, cancel this task and start new task.
*/
private void startBackgroundTimer() {
if (mBackgroundTimer != null) {
mBackgroundTimer.cancel();
}
mBackgroundTimer = new Timer();
/* set delay time to reduce too much background image loading process */
mBackgroundTimer.schedule(new UpdateBackgroundTask(), BACKGROUND_UPDATE_DELAY);
}
private class UpdateBackgroundTask extends TimerTask {
#Override
public void run() {
/* Here is TimerTask thread, not UI thread */
mHandler.post(new Runnable() {
#Override
public void run() {
/* Here is main (UI) thread */
if (mBackgroundURI != null) {
updateBackground(mBackgroundURI);
}
}
});
}
}
public void updateBackgroundWithDelay(String url) {
try {
URI uri = new URI(url);
updateBackgroundWithDelay(uri);
} catch (URISyntaxException e) {
/* skip updating background */
Log.e(TAG, e.toString());
}
}
/**
* updateBackground with delay
* delay time is measured in other Timer task thread.
* #param uri
*/
public void updateBackgroundWithDelay(URI uri) {
mBackgroundURI = uri;
startBackgroundTimer();
}
private void updateBackground(URI uri) {
try {
Picasso.with(mActivity)
.load(uri.toString())
.resize(mMetrics.widthPixels, mMetrics.heightPixels)
.centerCrop()
.error(mDefaultBackground)
.into(mBackgroundTarget);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
/**
* Copied from AOSP sample code.
* Inner class
* Picasso target for updating default_background images
*/
public class PicassoBackgroundManagerTarget implements Target {
BackgroundManager mBackgroundManager;
public PicassoBackgroundManagerTarget(BackgroundManager backgroundManager) {
this.mBackgroundManager = backgroundManager;
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) {
this.mBackgroundManager.setBitmap(bitmap);
}
#Override
public void onBitmapFailed(Drawable drawable) {
this.mBackgroundManager.setDrawable(drawable);
}
#Override
public void onPrepareLoad(Drawable drawable) {
// Do nothing, default_background manager has its own transitions
}
#Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
PicassoBackgroundManagerTarget that = (PicassoBackgroundManagerTarget) o;
if (!mBackgroundManager.equals(that.mBackgroundManager))
return false;
return true;
}
#Override
public int hashCode() {
return mBackgroundManager.hashCode();
}
}
}
Then in your activity or fragment use this snippet below
PicassoBackgroundManager picassoBackgroundManager = new PicassoBackgroundManager(getActivity());
picassoBackgroundManager.updateBackgroundWithDelay("some.image.url");
I have the following code:
/**
* Request wrapped around flowable.
*/
public abstract class RequestFlowable<T> {
private final PublishProcessor<String> mPublish;
private String mName;
public RequestFlowable(String name) {
mName = name;
mPublish = PublishProcessor.create();
}
public Flowable<T> getFlowable() {
//return createAction();
return mPublish.compose(new FlowableTransformer<String, T>() {
#Override
public Publisher<T> apply(#NonNull Flowable<String> upstream) {
return createAction();
}
});
/*
return mPublish.flatMap(new Function<String, Publisher<? extends T>>() {
#Override
public Publisher<? extends T> apply(#NonNull String s) throws Exception {
return createAction();
}
});
*/
}
protected abstract Flowable<T> createAction();
public String getName() {
return mName;
}
public void start() {
mPublish.onNext("processCommand");
}
#Override
public String toString() {
return "Request: " + mName;
}
}
Now for Single
#EDIT 2
public abstract class Request<T> {
private final SingleSubject<Object> mPublish;
private String mName;
public Request(String name) {
mName = name;
mPublish = SingleSubject.create();
}
public Single<T> getSingle() {
return mPublish.flatMap(o -> createAction());
}
protected abstract Single<? extends T> createAction();
public String getName() {
return mName;
}
public void start() {
mPublish.onSuccess("Start");
}
#Override
public String toString() {
return "Request: " + mName;
}
}
The code from the above works when used with compose, like in code from above but, if instead I put the commented code - aka flatMap for some reason createAction is not executed.
EDIT 2
The code from the above is called from another class. The corresponding code is attached below(important parts of class added):
public class RequestQueue implements RequestController {
private static final String TAG = RequestQueue.class.getSimpleName();
private PublishSubject<Request> mRequest;
private PublishSubject<RequestFlowable> mRequestFlowable;
#Override
public <T> Single<T> registerRequest(Request<T> request) {
mRequest.onNext(request);
return request.getSingle();
}
#Override
public <T> Flowable<T> registerRequestFlowable(RequestFlowable<T> request) {
mRequestFlowable.onNext(request);
return request.getFlowable();
}
public RequestQueue() {
mRequest = PublishSubject.create();
mRequestFlowable = PublishSubject.create();
mRequest.subscribe(this::actionOnRequest);
mRequestFlowable.subscribe(this::actionOnRequest);
}
private void actionOnRequest(Request request) {
Log.d(TAG, "actionOnRequest() called with: request = [" + request + "]");
request.start();
}
private void actionOnRequest(RequestFlowable request) {
Log.d(TAG, "actionOnRequest() called with: request = [" + request + "]");
request.start();
}
}
(From my comments:)
Why does Single work?
SingleSubject retains the single terminal event it received. Since it can only receive onSuccess and onError, it will "replay" that to late subscribers (also this is why there is no separater ReplaySingleSubject). When you call onSuccess on the SingleSubject, that value is remembered and promplty reemitted when the later subscription happens, calling your createAction. PublishProcessor also remembers its terminal events but onNext is not a terminal event, hence dropped without consumer.
How can the desired behavior be achieved via Processor?
You could reorganize your logic, use BehaviorProcessor or ReplayProcessor.createWithSize(1). Calling onComplete won't execute the flatMap function either.
In Picasso there exists the RequestHandler class. And I can add custom RequestHandlers to Picasso.
How can this be done in Glide?
I for example want that following URI can be handled by a custom RequestHandler: "appicon:custom_data_to_interprete_manually"
EDIT - what I have so far
public class GlideConfiguration implements GlideModule {
#Override
public void applyOptions(Context context, GlideBuilder builder) {
// Apply options to the builder here.
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
#Override
public void registerComponents(Context context, Glide glide) {
glide.register(CustomModelParams.class, CustomModelParams.class, new CustomFactory());
}
class CustomModelParams
{
final String data;
public CustomModelParams(String data)
{
this.data = data;
}
public String getId()
{
return data;
}
}
class CustomFactory implements ModelLoaderFactory<CustomModelParams, CustomModelParams>
{
#Override
public ModelLoader<CustomModelParams, CustomModelParams> build(Context context, GenericLoaderFactory loaderFactory) {
return new CustomModelLoader();
}
#Override
public void teardown() {
}
}
class CustomModelLoader implements ModelLoader<CustomModelParams, CustomModelParams>
{
public CustomModelLoader() {
super();
}
#Override
public DataFetcher<CustomModelParams> getResourceFetcher(final CustomModelParams model, int width, int height)
{
return new DataFetcher<CustomModelParams>()
{
#Override
public CustomModelParams loadData(Priority priority) throws Exception { return model; }
#Override
public void cleanup() { }
#Override
public String getId() { return model.getId(); }
#Override
public void cancel() { }
};
}
}
class CustomBitmapDecoder implements ResourceDecoder<CustomModelParams, Bitmap>
{
private final Context context;
public CustomBitmapDecoder(Context context)
{
this.context = context;
}
#Override
public Resource<Bitmap> decode(CustomModelParams source, int width, int height) throws IOException
{
BitmapPool pool = Glide.get(context).getBitmapPool();
Bitmap bitmap = pool.getDirty(width, height, Bitmap.Config.ARGB_8888);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
// TODO
// create custom bitmap from CustomModelParams!!!
return BitmapResource.obtain(bitmap, pool);
}
#Override
public String getId()
{
return CustomBitmapDecoder.class.getName();
}
}
}
QUESTION
How do I link those classes together? The Decoder must somehow be linked with the new Model
How do I define, that my custom loader can handle a request? I have to somehow determine if the url I get can be handled by this loader...
You can use ModelLoaders. See the Downloading custom sizes wiki for an example of a custom ModelLoader. Note that instead of a BaseGlideUrlLoader, you will want to register a ModelLoader that handles your particular data model.
I have implemented very simular code for my project (It loads other applications icons from Package Manager) and
#Override
public void registerComponents(Context context, Glide glide) {
glide.register(MyDataModel.class, Bitmap.class, new MyUrlLoader.Factory());
}
doesn't work for me.
So to make custom loaded works I just use Glide Builder
private final GenericRequestBuilder<MyDataModel, Bitmap, Bitmap, Bitmap> mGlideBuilder;
mGlideBuilder = Glide.with(mContext)
.using(new MyUrlLoader(mContext), Bitmap.class)
.from(MyDataModel.class)
.as(Bitmap.class)
.decoder(new MyBitmapDecoder())
.diskCacheStrategy(DiskCacheStrategy.NONE);
mGlideBuilder.load(entry).into(holder.icon);
and MyBitmapDecoder and MyUrlLoader declared as
public class MyBitmapDecoder implements ResourceDecoder<Bitmap, Bitmap> {
public class MyUrlLoader implements ModelLoader<MyDataModel, Bitmap> {