@rookiedev是正确的,Glide中没有load(Bitmap)
这个方法, 因为获取Bitmap
通常需要时间并且有时会阻塞I/O。因此,在UI线程上调用imageWithText
不是一个好的实践。更新: 话虽如此,我曾经提出过这个功能; 尽管使用传统方法更容易,但下面你可以找到“Glide方式”,我强烈推荐。
Glide被设计成具有灵活性,这个问题非常好地展示了这一特点。以下实现可能看起来很长,但所有部分都有其存在的原因。考虑到性能增益,为适应Glide的世界而编写此代码量并不多。 我试图将其格式化为简短形式,折叠无关部分并使用静态导入使其更短(请参见导入末尾)。
该代码还包括以编程方式生成的UI,因此您可以将下面的所有代码复制粘贴到GlideGeneratedImageListFragment.java
中并运行它;唯一的外部依赖项是支持lib的RecyclerView
。
class GeneratingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final GenericRequestBuilder<GenerateParams, GenerateParams, Bitmap, GlideDrawable> generator;
public GeneratingAdapter(final Context context) {
generator = Glide
.with(context)
.using(new GenerateParamsPassthroughModelLoader(), GenerateParams.class)
.from(GenerateParams.class)
.as(Bitmap.class)
.transcode(new BitmapToGlideDrawableTranscoder(context), GlideDrawable.class)
.decoder(new GenerateParamsBitmapResourceDecoder(context))
.encoder(new BitmapEncoder(Bitmap.CompressFormat.PNG, 0))
.cacheDecoder(new FileToStreamDecoder<Bitmap>(new StreamBitmapDecoder(context)))
.error(new ColorDrawable(Color.RED))
;
}
@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;
GenerateParams params = new GenerateParams(
"android text",
Color.HSVToColor(colorCache),
Color.HSVToColor(bgCache)
);
generator.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) {};
}
}
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 ));
view.setAdapter(new GeneratingAdapter(view.getContext()));
return view;
}
}
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() {
return String.format(Locale.ROOT, "%s-%08x-%08x", text, color, background);
}
}
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() { }
};
}
}
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() {
return "com.example.MyImageGenerator";
}
}
class Generators {
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 );
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;
}
public static Bitmap imageWithTextNoLayout(Context context, Bitmap bitmap, GenerateParams params) {
Paint paint = new Paint();
paint.setColor(params.color);
paint.setTextAlign(Paint.Align.CENTER);
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;
}
}
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 帧率很低):
注意它如何加载前几个项目,然后逐渐加载其余项目。需要一点时间来让内存缓存和池热起来,但如果您想要更平滑的显示,可以使用预加载器。在热身后,它可以很好地滚动。操作栏上的删除按钮调用
Glide.clearDiskCache()
和
Glide.clearMemory()
,因此它会重新生成项目。
Class.method(args)
,以显示按钮的功能并非神奇。clearMemory
应该在UI线程上调用,否则你可能会遇到一些意外情况。 - TWiStErRob