前言:其实这个bug我1月份就遇到了,当时康师傅用的是毕加索,我用的是Glide,然后就报了个空指针异常了,今天群里又有同学在说这个bug,那我就给大家提供一下解决方案吧~
使用Glide加载图片的时候需要注意,因为Glide加载图片时是异步加载的。所以在后面直接调用ImageView对象的getDrawable()方法可能会出现空指针异常。
log如下:
--------- 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
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
/**
* 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;
}
}
如果你也遇到过这个问题,那么你就可以通过这两种方式(不太建议第一种,因为你延迟的时机可能并不准确,有的图片可能在那个时间内可以加载完成,遇到大一点的图片或者网络不好时就没办法了)进行解决啦~
如果本文解决了你的问题或者你觉得有用,那就点个赞再走呗~
本文由
A lonely cat
原创发布于
阳光沙滩
,未经作者授权,禁止转载