Использование Glide для загрузки растрового изображения в ImageView

Как я могу использовать библиотеку Glide для загрузки Bitmap в свой ImageView? Я хочу создать собственное изображение с текстом и загрузить его в изображение с помощью Glide.

Это мой метод создания пользовательского растрового изображения с текстом

public Bitmap imageWithText(String text) { TextView tv = new TextView(context); tv.setText(text); tv.setTextColor(Color.WHITE); tv.setBackgroundColor(Color.BLACK); tv.setTypeface(null, Typeface.BOLD); tv.setGravity(Gravity.CENTER); tv.setTextSize(20); tv.setPadding(0, 25, 0, 0); Bitmap testB = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(testB); tv.layout(0, 0, 100, 100); tv.draw(c); return testB; } 

Но когда я пытаюсь загрузить это растровое изображение с помощью glide, я получаю ошибку

 Glide.with(getContext()).load(imageWithText("Random text")).into(holder.imgPhoto); 

@rookiedev прав, в Glide нет load(Bitmap) , по какой-то причине: получение Bitmap обычно требует времени и иногда блокирует ввод-вывод. Поэтому неплохо было бы вызвать imageWithText в потоке пользовательского интерфейса. Обновление : при этом я предложил эту функцию некоторое время назад; И в то время как хаки легче сделать, вы можете найти «Glide way» ниже, что я настоятельно рекомендую.

Glide разработан, чтобы быть гибким, и эта проблема очень хорошо демонстрирует эту черту. Следующая реализация может показаться длинной, но все части имеют свои основания для существования. Учитывая прирост производительности, этот объем кода, который подходит вашему генератору в мире Glide, не так уж много. Я попытался отформатировать его, чтобы быть коротким, рушиться нерелевантными частями и использовать статический импорт, чтобы быть короче (см. Конец для импорта).

Код также включает в себя программно сгенерированный интерфейс, поэтому вы можете просто скопировать-вставить весь приведенный ниже код в GlideGeneratedImageListFragment.java и запустить его; Единственной внешней зависимостью является RecyclerView поддержки lib.

 class GeneratingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { // See https://docs.google.com/drawings/d/1KyOJkNd5Dlm8_awZpftzW7KtqgNR6GURvuF6RfB210g/edit?usp=sharing // ModelType/A, DataType/T, ResourceType/Z, TranscodeType/R private final GenericRequestBuilder<GenerateParams, GenerateParams, Bitmap, GlideDrawable> generator; public GeneratingAdapter(final Context context) { generator = Glide // this part should be cleaner in Glide 4.0, but that's not released yet .with(context) .using(new GenerateParamsPassthroughModelLoader(), GenerateParams.class) // custom class .from(GenerateParams.class) .as(Bitmap.class) .transcode(new BitmapToGlideDrawableTranscoder(context), GlideDrawable.class) // builtin .decoder(new GenerateParamsBitmapResourceDecoder(context)) // custom class .encoder(new BitmapEncoder(Bitmap.CompressFormat.PNG, 0/*ignored for lossless*/)) // builtin .cacheDecoder(new FileToStreamDecoder<Bitmap>(new StreamBitmapDecoder(context))) // builtin //.placeholder(new ColorDrawable(Color.YELLOW)) // you can pre-set placeholder and error .error(new ColorDrawable(Color.RED)) // so it's easier when binding //.diskCacheStrategy(DiskCacheStrategy.NONE) // only for debugging to always regenerate //.skipMemoryCache(true) // only for debugging to always regenerate ; } @Override public int getItemCount() { return 1000; } private final float[] colorCache = new float[] {0, 1.0f, 0.5f}; private final float[] bgCache = new float[] {0, 0.5f, 1.0f}; @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { colorCache[0] = bgCache[0] = (position * 15) % 360; // just to have a fancy example :) GenerateParams params = new GenerateParams( // omit position to see Glide caching in action (every 24th item / 12th row is the same) "android text"/* + " #" + position*/, Color.HSVToColor(colorCache), Color.HSVToColor(bgCache) ); generator/*.clone() in case you see weird behavior*/.load(params).into((ImageView)holder.itemView); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { int height = parent.getContext().getResources().getDisplayMetrics().heightPixels / 3; ImageView view = new ImageView(parent.getContext()); view.setLayoutParams(new RecyclerView.LayoutParams(MATCH_PARENT, height)); view.setScaleType(ImageView.ScaleType.FIT_CENTER); return new RecyclerView.ViewHolder(view) {}; // anon class for brevity } } public class GlideGeneratedImageListFragment extends Fragment { @Override public @Nullable View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { RecyclerView view = new RecyclerView(container.getContext()); view.setLayoutParams(new MarginLayoutParams(MATCH_PARENT, MATCH_PARENT)); view.setLayoutManager(new GridLayoutManager(container.getContext(), 2 /*columns*/)); view.setAdapter(new GeneratingAdapter(view.getContext())); return view; } } /** Extracted params from imageWithText, but left some hardcoded values like 20sp/bold/center in {@link Generators}. */ class GenerateParams { final String text; final int color; final int background; public GenerateParams(String text, int color, int bg) { this.text = text; this.color = color; this.background = bg; } public String getId() { // TODO make sure it's unique for every possible instance of GenerateParams // because it will affect how the resulting bitmap is cached // the below is correct correct for the current fields, if those change this has to change return String.format(Locale.ROOT, "%s-%08x-%08x", text, color, background); } } /** Boilerplate because of the degeneration in ModelType == DataType, but important for caching. * @see GeneratingAdapter#generator */ class GenerateParamsPassthroughModelLoader implements ModelLoader<GenerateParams, GenerateParams> { @Override public DataFetcher<GenerateParams> getResourceFetcher(final GenerateParams model, int width, int height) { return new DataFetcher<GenerateParams>() { @Override public GenerateParams loadData(Priority priority) throws Exception { return model; } @Override public void cleanup() { } @Override public String getId() { return model.getId(); } @Override public void cancel() { } }; } } /** Handles pooling to reduce/prevent GC lagging from too many {@link Bitmap#createBitmap}s */ class GenerateParamsBitmapResourceDecoder implements ResourceDecoder<GenerateParams, Bitmap> { private final Context context; public GenerateParamsBitmapResourceDecoder(Context context) { this.context = context; } @Override public Resource<Bitmap> decode(GenerateParams 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); } Generators.imageWithTextNoLayout(context, bitmap, source); return BitmapResource.obtain(bitmap, pool); } @Override public String getId() { // be careful if you change the Generator implementation you have to change this // otherwise the users may see a cached image; or clear cache on app update return "com.example.MyImageGenerator"; } } class Generators { /** OP's original implementation fixed for real centering */ public static Bitmap imageWithText(Context context, Bitmap bitmap, GenerateParams params) { TextView view = new TextView(context); view.setText(params.text); view.setTextColor(params.color); view.setBackgroundColor(params.background); view.setTypeface(null, Typeface.BOLD); view.setGravity(Gravity.CENTER); view.setTextSize(20 /*sp*/); Canvas canvas = new Canvas(bitmap); view.measure(makeMeasureSpec(canvas.getWidth(), EXACTLY), makeMeasureSpec(canvas.getHeight(), EXACTLY)); view.layout(0, 0, canvas.getWidth(), canvas.getHeight()); view.draw(canvas); return bitmap; } /** Generate centered text without creating a View, more lightweight. * Consider https://stackoverflow.com/a/8369690/253468 for multiline support. */ public static Bitmap imageWithTextNoLayout(Context context, Bitmap bitmap, GenerateParams params) { Paint paint = new Paint(); paint.setColor(params.color); paint.setTextAlign(Paint.Align.CENTER); // text's anchor for the x given in drawText paint.setTextSize(applyDimension(COMPLEX_UNIT_SP, 20, context.getResources().getDisplayMetrics())); paint.setTypeface(Typeface.DEFAULT_BOLD); Canvas canvas = new Canvas(bitmap); canvas.drawColor(params.background); canvas.drawText(params.text, canvas.getWidth() / 2, canvas.getHeight() / 2, paint); return bitmap; } } // Here are the imports in case you need it; // didn't want to put it in the beginning to keep the relevant code first. import java.io.IOException; import java.util.Locale; import android.content.Context; import android.graphics.*; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.*; import android.view.*; import android.view.ViewGroup.MarginLayoutParams; import android.widget.*; import static android.util.TypedValue.*; import static android.view.View.MeasureSpec.*; import static android.view.ViewGroup.LayoutParams.*; import com.bumptech.glide.*; import com.bumptech.glide.load.ResourceDecoder; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.engine.Resource; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.resource.bitmap.*; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.load.resource.file.FileToStreamDecoder; import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder; 

Вот как это выглядит (реальная прокрутка намного более плавная, GIF – действительно низкий FPS):

Введите описание изображения здесь

Обратите внимание, как он загружает первые несколько элементов, а затем постепенно загружает остальные. Требуется немного, чтобы кеш памяти и пул нагревались, но вы можете использовать предварительный загрузчик, если хотите еще более плавный дисплей. После того, как он разогревается, он прокручивает красиво. Кнопка удаления на панели действий вызывает Glide.clearDiskCache() и Glide.clearMemory() чтобы снова начать регенерировать элементы.

Я не знаю производительности, но вы можете попробовать это:

Прежде всего преобразуйте растровое изображение в массив byte []:

 private byte[] bitmapToByte(Bitmap bitmap){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); byte[] byteArray = stream.toByteArray(); return byteArray; } 

Затем используйте глиссирование таким образом:

 Glide.with(holder.imagePhoto.getContext()).load(bitmapToByte(yourBitmap)).asBitmap().override(300, 300).fitCenter().into(holder.imagePhoto); 

В твоем случае:

 Glide.with(holder.imagePhoto.getContext()).load(bitmapToByte(yourBitmap)).asBitmap().into(holder.imagePhoto); //>>not tested 

Согласно документации, я не думаю, что метод load () может принимать параметр Bitmap как параметр. Источник изображения (т. Е. Параметр) может быть URL, ресурсом и файлом.

Однако, если вы хотите загрузить Bitmap в ImageView, вам не нужно использовать библиотеку Glide. Просто используйте приведенный ниже оператор

 holder.imgPhoto.setImageBitmap(imageWithText("Random text"));