从工具类PhotoManager启动Activity遇空指针问题求助
首先咱们来拆解你遇到的空指针问题:
你在PhotoManager的userWantsToUploadPicture()方法里直接调用了startActivityForResult(),但这个方法是Activity类的专属成员方法,而PhotoManager只是一个普通工具类,并非Activity的子类。直接调用它时,系统找不到对应的ActivityThread上下文,自然就抛出了空指针异常。
至于这段逻辑在更新头像的类里能正常工作,原因很简单:那个类本身就是Activity(或者依附于Activity的Fragment),直接调用startActivityForResult()是在使用自身的Activity上下文,所以不会出问题。
修复步骤
1. 修正startActivityForResult的调用方式
你已经在PhotoManager的构造方法里传入了Activity实例,所以必须通过这个实例来调用startActivityForResult:
public Bitmap userWantsToUploadPicture(){ int permissionChecker = ContextCompat.checkSelfPermission(context, android.Manifest.permission.READ_EXTERNAL_STORAGE); if(permissionChecker == PackageManager.PERMISSION_GRANTED){ // 改为通过传入的activity实例调用方法 activity.startActivityForResult(new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI), SELECT_FILE); // 注意:这里直接返回selectedImage是无效的! return selectedImage; } else{ // 补充权限请求逻辑 ActivityCompat.requestPermissions(activity, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_PERMISSION_CODE); } return null; }
2. 处理异步结果的核心问题
这里要重点提醒:startActivityForResult是异步操作,你调用它之后立刻返回selectedImage,此时用户还没完成图片选择,selectedImage肯定是空的。
你需要在传入的Activity里重写onActivityResult方法,拿到选择的图片后再处理:
比如在你的Activity中:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PhotoManager.SELECT_FILE && resultCode == RESULT_OK && data != null) { Uri selectedUri = data.getData(); // 将Uri转换为Bitmap try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedUri); // 直接更新头像或回调给PhotoManager处理 profilePic.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } }
3. 完善权限请求的回调逻辑
当权限被拒绝后,需要在Activity里处理权限请求结果,重新触发图片选择:
在Activity中重写:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PhotoManager.REQUEST_PERMISSION_CODE) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限授予成功,重新调用图片选择方法 photoManager.userWantsToUploadPicture(); } else { // 提示用户开启权限 Toast.makeText(this, "需要存储权限才能选择图片", Toast.LENGTH_SHORT).show(); } } }
补充优化建议
建议在PhotoManager里定义统一的常量,方便Activity里判断:
public class PhotoManager { public static final int SELECT_FILE = 100; public static final int REQUEST_PERMISSION_CODE = 200; // ... 其他成员变量和方法 }
这样修改后,你的PhotoManager就能正常调用图库/相机,并且正确获取返回的图片了。
内容的提问来源于stack exchange,提问作者Taylor Barton

