Android开发:从Activity传选中图片到Fragment遇空指针异常求助
我是Android开发新手,想把第一个Activity里GridView选中的图片在另一个Fragment中展示,但碰到了空指针错误,折腾了好久找不到问题所在,求助大家!
相关代码
GridView选中图片的回调代码
@Override public void onGridImageSelected(Photo photo, int activityNumber) { Log.d(TAG, "onGridImageSelected: selected an image gridview: " + photo.toString()); FullScreenProductFragment fragment = new FullScreenProductFragment(); Bundle args = new Bundle(); args.putParcelable(getString(R.string.photo), photo); args.putInt(getString(R.string.activity_number), activityNumber); fragment.setArguments(args); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.Profilecontainer, fragment); transaction.addToBackStack(getString(R.string.view_post_fragment)); transaction.commit(); }
展示图片的Fragment代码
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragmentfullscreenlayout, container, false); mImageView = view.findViewById(R.id.zoom_image); Bundle bundle = getActivity().getIntent().getExtras(); // 这行是无用代码 UnivarsalImageLoader.setImage(getPhotoFromBundle().getImage_path(),mImageView, null, ""); Log.d(TAG, "onCreateView: getphoto from bundle"+getPhotoFromBundle().getImage_path()); return view; } private Photo getPhotoFromBundle(){ Log.d(TAG, "getPhotoFragment: argumentd"+getArguments()); Bundle bundle = this.getArguments(); if (bundle != null){ return bundle.getParcelable(getString(R.string.photo)); }else { return null; } }
错误日志
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.alpha.lapid.models.Photo.getImage_path()' on a null object reference at com.example.alpha.lapid.Utils.FullScreenProductFragment.onCreateView(FullScreenProductFragment.java:56) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2346) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1428)
调试日志
05-20 08:52:23.534 668-668/com.example.alpha.lapid D/FullScreenProductFragme: getPhotoFragment: argumentdBundle[{}]
问题分析与解决方案
嘿,我帮你排查了下代码,问题主要出在数据传递的key不匹配和缺少空值判断这两个地方,另外还有一段无用代码干扰了调试,具体来说:
1. 核心问题:字符串资源作为key可能不匹配
你在Activity里用getString(R.string.photo)作为Parcelable的key,在Fragment里也用同样的方式获取,但如果两个地方的R.string.photo对应的实际字符串不一致(比如资源文件写错、多语言配置差异),就会导致Fragment从Arguments里拿不到Photo对象,返回null后调用getImage_path()就触发了空指针。
2. 次要问题:无用代码+缺少空值判断
Fragment里的Bundle bundle = getActivity().getIntent().getExtras();完全没用,而且你直接调用getPhotoFromBundle().getImage_path(),没有先判断返回的Photo是否为null,这会放大空指针问题。
具体修复步骤
第一步:改用常量字符串作为传递key
在Activity和Fragment中定义统一的常量(可以放在一个公共类里,或者各自类里定义相同值):
// 在Activity和Fragment中都添加这两行 public static final String KEY_PHOTO = "selected_photo"; public static final String KEY_ACTIVITY_NUMBER = "activity_number";
然后修改Activity里的传参代码:
args.putParcelable(KEY_PHOTO, photo); args.putInt(KEY_ACTIVITY_NUMBER, activityNumber);
Fragment里的getPhotoFromBundle()方法修改为:
private Photo getPhotoFromBundle(){ Log.d(TAG, "getPhotoFragment: arguments"+getArguments()); Bundle bundle = this.getArguments(); if (bundle != null){ return bundle.getParcelable(KEY_PHOTO); }else { return null; } }
第二步:检查Photo类的Parcelable实现是否正确
确保你的Photo类完整实现了Parcelable接口,所有字段都正确序列化和反序列化,示例如下:
public class Photo implements Parcelable { private String image_path; // 其他字段请自行补充 // 构造方法 public Photo() {} // Parcelable构造方法 protected Photo(Parcel in) { image_path = in.readString(); // 读取其他字段,比如in.readInt()、in.readBoolean()等 } public static final Creator<Photo> CREATOR = new Creator<Photo>() { @Override public Photo createFromParcel(Parcel in) { return new Photo(in); } @Override public Photo[] newArray(int size) { return new Photo[size]; } }; @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(image_path); // 写入其他字段 } @Override public int describeContents() { return 0; } // getter方法 public String getImage_path() { return image_path; } }
第三步:修复Fragment的onCreateView方法
移除无用代码,添加空值判断:
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragmentfullscreenlayout, container, false); mImageView = view.findViewById(R.id.zoom_image); Photo selectedPhoto = getPhotoFromBundle(); if (selectedPhoto != null) { UnivarsalImageLoader.setImage(selectedPhoto.getImage_path(), mImageView, null, ""); Log.d(TAG, "onCreateView: getphoto from bundle"+selectedPhoto.getImage_path()); } else { Log.e(TAG, "onCreateView: 选中的图片为空"); // 这里可以添加默认图片展示逻辑,比如mImageView.setImageResource(R.drawable.default_img); } return view; }
额外建议
如果还是有问题,可以在Activity的onGridImageSelected方法里打印args的内容,确认Photo对象已经正确放入Bundle中;同时检查Fragment的容器IDR.id.Profilecontainer是否在Activity布局中存在,确保Fragment能正确附加到Activity上。
内容的提问来源于stack exchange,提问作者lllllllllllllll

