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
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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With