You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Java实现相册选图显示时点击按钮崩溃求助

Android 相册选图崩溃问题解决(非静态类场景)

问题描述

在Android Java开发中,尝试实现点击按钮从相册选图并显示到ImageView,但每次点击按钮应用崩溃。已在Manifest中添加外部存储权限,尝试过废弃的startActivityForResult,当前代码运行在主Activity调用的非静态类中,使用ActivityResultLauncher实现,但触发NullPointerException。

原代码

ActivityResultLauncher<String> launcher = registerForActivityResult
    (new ActivityResultContracts.GetContent(), new ActivityResultCallback<Uri> () {
        @Override public void onActivityResult (Uri uri) {
            images.setImageURI(uri);
        } });
image.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        launcher.launch("image/*");
    }
});

错误日志

FATAL EXCEPTION: main
Process: com.an.rindr, PID: 13121
java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference
    at android.app.Activity.startActivityForResult(Activity.java:5584)
    at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:728)
    at androidx.core.app.ActivityCompat$Api16Impl.startActivityForResult(ActivityCompat.java:809)
    at androidx.core.app.ActivityCompat.startActivityForResult(ActivityCompat.java:246)
    at androidx.activity.ComponentActivity$2.onLaunch(ComponentActivity.java:243)
    at androidx.activity.result.ActivityResultRegistry$2.launch(ActivityResultRegistry.java:175)
    at androidx.activity.result.ActivityResultLauncher.launch(ActivityResultLauncher.java:47)
    at com.an.rindr.home$2.onClick(home.java:152)
    at android.view.View.performClick(View.java:7881)
    at android.widget.TextView.performClick(TextView.java:16201)
    at android.view.View.performClickInternal(View.java:7858)
    at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0)
    at android.view.View$PerformClick.run(View.java:30863)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:226)
    at android.os.Looper.loop(Looper.java:313)
    at android.app.ActivityThread.main(ActivityThread.java:8741)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

错误原因

  1. registerForActivityResult调用时机错误:该方法必须在Activity的生命周期初始化阶段(如onCreate)调用,依赖Activity的ActivityResultRegistry才能正常工作。如果在非静态类的构造方法或非生命周期方法中调用,会导致Activity关联的系统引用为空。
  2. 非静态类持有无效Activity引用:如果非静态类未正确持有存活的Activity实例,或Activity已被销毁,调用launch时会触发空指针异常。

解决方案

核心修复点

  • 将ActivityResultLauncher的注册移到Activity的onCreate方法中,确保在Activity生命周期内完成注册。
  • 非静态类通过弱引用持有Activity,避免内存泄漏,同时在调用launch前检查Activity是否存活。
  • Android 10+使用GetContent()无需申请外部存储权限,可移除不必要的权限声明。

完整代码示例

public class MainActivity extends AppCompatActivity {
    private ActivityResultLauncher<String> imagePickerLauncher;
    private ImageView images;
    private HomeHelper homeHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化ImageView
        images = findViewById(R.id.images);
        // 必须在Activity onCreate中注册Launcher
        imagePickerLauncher = registerForActivityResult(
                new ActivityResultContracts.GetContent(),
                uri -> {
                    if (uri != null) {
                        images.setImageURI(uri);
                    }
                }
        );

        // 初始化非静态类,传入弱引用的Activity和已注册的Launcher
        homeHelper = new HomeHelper(this, imagePickerLauncher);
        // 绑定按钮点击事件
        TextView imageButton = findViewById(R.id.image);
        imageButton.setOnClickListener(v -> homeHelper.launchImagePicker());
    }

    // 你的非静态业务类
    public class HomeHelper {
        private WeakReference<AppCompatActivity> activityWeakRef;
        private ActivityResultLauncher<String> imageLauncher;

        public HomeHelper(AppCompatActivity activity, ActivityResultLauncher<String> launcher) {
            this.activityWeakRef = new WeakReference<>(activity);
            this.imageLauncher = launcher;
        }

        public void launchImagePicker() {
            // 检查Activity是否存活,避免空指针
            AppCompatActivity activity = activityWeakRef.get();
            if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
                imageLauncher.launch("image/*");
            }
        }
    }
}

额外注意事项

  • 若需兼容Android 9及以下,可保留READ_EXTERNAL_STORAGE权限,但需动态申请。
  • 避免在非静态类中直接持有Activity强引用,防止内存泄漏。
  • 在回调中判断uri是否为空,避免空指针。

内容的提问来源于stack exchange,提问作者king cannibal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 19:09:31