关于使用Glide加载图片你需要知道的

前言:其实这个bug我1月份就遇到了,当时康师傅用的是毕加索,我用的是Glide,然后就报了个空指针异常了,今天群里又有同学在说这个bug,那我就给大家提供一下解决方案吧~

使用Glide加载图片的时候需要注意,因为Glide加载图片时是异步加载的。所以在后面直接调用ImageView对象的getDrawable()方法可能会出现空指针异常。

log如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

--------- beginning of crash
2020-06-11 20:23:07.806 27136-27136/com.smart.himalaya E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.smart.himalaya, PID: 27136
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.smart.himalaya/com.smart.himalaya.DetailActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.Bitmap android.graphics.drawable.BitmapDrawable.getBitmap()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.Bitmap android.graphics.drawable.BitmapDrawable.getBitmap()' on a null object reference
at com.smart.himalaya.utils.ImageBlur.makeBlur(ImageBlur.java:15)
at com.smart.himalaya.DetailActivity.onAlbumLoaded(DetailActivity.java:298)
at com.smart.himalaya.presenters.AlbumDetailPresenter.registerViewCallback(AlbumDetailPresenter.java:133)
at com.smart.himalaya.DetailActivity.initPresenter(DetailActivity.java:104)
at com.smart.himalaya.DetailActivity.onCreate(DetailActivity.java:83)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016
at android.os.Handler.dispatchMessage(Handler.java:107
at android.os.Looper.loop(Looper.java:214
at android.app.ActivityThread.main(ActivityThread.java:7356
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930

图片描述

图片描述

解决办法如下:

  1. 使用Handler延时处理(处理之前还是得先判空才行)
  2. 使用Glide的图片加载监听器(推荐)

方法一:使用Handler:

图片描述

方法二:使用Glide的监听器:

图片描述

我们还需要改造一下ImageBlur工具类(用到了一个将Drawable对象转换成Bitmap对象的工具类):

ImageBlur.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

public class ImageBlur {
public static void makeBlur(Context context, ImageView imageview) {
BitmapDrawable drawable = (BitmapDrawable) imageview.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Bitmap blurred = blurRenderScript(bitmap, 10, context); //second parametre is radius max:25
imageview.setImageBitmap(blurred); //radius decide blur amount
}

public static void makeBlur(Context context, Drawable drawable, ImageView imageView) {
Bitmap bitmap = ImageTools.drawableToBitmap(drawable);
Bitmap blurred = blurRenderScript(bitmap, 10, context); //second parametre is radius max:25
imageView.setImageBitmap(blurred); //radius decide blur amount
}

public static void makeBlur(Context context, Bitmap bitmap, ImageView imageview) {
Bitmap blurred = blurRenderScript(bitmap, 10, context); //second parametre is radius max:25
imageview.setImageBitmap(blurred); //radius decide blur amount
}

private static Bitmap blurRenderScript(Bitmap smallBitmap, int radius, Context context) {
smallBitmap = RGB565toARGB888(smallBitmap);
Bitmap bitmap = Bitmap.createBitmap(smallBitmap.getWidth(), smallBitmap.getHeight(), Bitmap.Config.ARGB_8888);
RenderScript renderScript = RenderScript.create(context);
Allocation blurInput = Allocation.createFromBitmap(renderScript, smallBitmap);
Allocation blurOutput = Allocation.createFromBitmap(renderScript, bitmap);
ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
blur.setInput(blurInput);
blur.setRadius(radius); // radius must be 0 < r <= 25
blur.forEach(blurOutput);
blurOutput.copyTo(bitmap);
renderScript.destroy();
return bitmap;
}

private static Bitmap RGB565toARGB888(Bitmap img) {
int numPixels = img.getWidth() * img.getHeight();
int[] pixels = new int[numPixels];

//Get JPEG pixels. Each int is the color values for one pixel.
img.getPixels(pixels, 0, img.getWidth(), 0, 0, img.getWidth(), img.getHeight());

//Create a Bitmap of the appropriate format.
Bitmap result = Bitmap.createBitmap(img.getWidth(), img.getHeight(), Bitmap.Config.ARGB_8888);

//Set RGB pixels.
result.setPixels(pixels, 0, result.getWidth(), 0, 0, result.getWidth(), result.getHeight());
return result;
}
}

ImageTools.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

/**
* Tools for handler picture
*
* @author Ryan.Tang
*/
public final class ImageTools {

/**
* Transfer drawable to bitmap 把drawable转换为bitmap
*
* @param drawable
* @return
*/
public static Bitmap drawableToBitmap(Drawable drawable) {
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();

Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
: Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}

/**
* Bitmap to drawable
*
* @param bitmap
* @return
*/
public static Drawable bitmapToDrawable(Bitmap bitmap) {
return new BitmapDrawable(bitmap);
}

/**
* Input stream to bitmap
*
* @param inputStream
* @return
* @throws Exception
*/
public static Bitmap inputStreamToBitmap(InputStream inputStream)
throws Exception {
return BitmapFactory.decodeStream(inputStream);
}

/**
* Byte transfer to bitmap
*
* @param byteArray
* @return
*/
public static Bitmap byteToBitmap(byte[] byteArray) {
if (byteArray.length != 0) {
return BitmapFactory
.decodeByteArray(byteArray, 0, byteArray.length);
} else {
return null;
}
}

/**
* Byte transfer to drawable
*
* @param byteArray
* @return
*/
public static Drawable byteToDrawable(byte[] byteArray) {
ByteArrayInputStream ins = null;
if (byteArray != null) {
ins = new ByteArrayInputStream(byteArray);
}
return Drawable.createFromStream(ins, null);
}

/**
* Bitmap transfer to bytes
*
* @return
*/
public static byte[] bitmapToBytes(Bitmap bm) {
byte[] bytes = null;
if (bm != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
bytes = baos.toByteArray();
}
return bytes;
}

/**
* Drawable transfer to bytes
*
* @param drawable
* @return
*/
public static byte[] drawableToBytes(Drawable drawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
byte[] bytes = bitmapToBytes(bitmap);
;
return bytes;
}

/**
* Base64 to byte[]
// */
// public static byte[] base64ToBytes(String base64) throws IOException {
// byte[] bytes = Base64.decode(base64);
// return bytes;
// }
//
// /**
// * Byte[] to base64
// */
// public static String bytesTobase64(byte[] bytes) {
// String base64 = Base64.encode(bytes);
// return base64;
// }

/**
* Create reflection images
*
* @param bitmap
* @return
*/
public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
final int reflectionGap = 4;
int w = bitmap.getWidth();
int h = bitmap.getHeight();

Matrix matrix = new Matrix();
matrix.preScale(1, -1);

Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, h / 2, w,
h / 2, matrix, false);

Bitmap bitmapWithReflection = Bitmap.createBitmap(w, (h + h / 2),
Config.ARGB_8888);

Canvas canvas = new Canvas(bitmapWithReflection);
canvas.drawBitmap(bitmap, 0, 0, null);
Paint deafalutPaint = new Paint();
canvas.drawRect(0, h, w, h + reflectionGap, deafalutPaint);

canvas.drawBitmap(reflectionImage, 0, h + reflectionGap, null);

Paint paint = new Paint();
LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
0x00ffffff, TileMode.CLAMP);
paint.setShader(shader);
// Set the Transfer mode to be porter duff and destination in
paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
// Draw a rectangle using the paint with our linear gradient
canvas.drawRect(0, h, w, bitmapWithReflection.getHeight()
+ reflectionGap, paint);

return bitmapWithReflection;
}


public static boolean copyFileUsingFileChannels(File source, File dest, boolean shouldDelete) {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
if (shouldDelete) {
//如果需要删除源文件
if (source.exists()) {
source.delete();
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
} finally {
try {
inputChannel.close();
outputChannel.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
}

return true;
}

public static Bitmap decodeUriAsBitmap(Uri uri, Context context) {
Bitmap bitmap = null;
try {
// 先通过getContentResolver方法获得一个ContentResolver实例,
// 调用openInputStream(Uri)方法获得uri关联的数据流stream
// 把上一步获得的数据流解析成为bitmap
bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri));
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
return bitmap;
}

}

如果你也遇到过这个问题,那么你就可以通过这两种方式(不太建议第一种,因为你延迟的时机可能并不准确,有的图片可能在那个时间内可以加载完成,遇到大一点的图片或者网络不好时就没办法了)进行解决啦~

如果本文解决了你的问题或者你觉得有用,那就点个赞再走呗~


关于使用Glide加载图片你需要知道的
https://blog.funkt.cn/2020/06/11/1271053904024469504/
作者
anjiemo
发布于
2020年6月11日
许可协议
未经作者授权,禁止转载