【问题标题】:Showing ImageView using BitmapFactory and file path, returns NullPointerException使用 BitmapFactory 和文件路径显示 ImageView,返回 NullPointerException
【发布时间】:2014-10-11 22:51:12
【问题描述】:

UPDATE2:问题与onResumeonPause 有关。它与BitmapFactory.decodeFile() 无关。问题是当我去拍照时,onPause 被调用,但没有任何东西被保存到SharedPreferences,因为还没有任何东西要保存。但是一旦我从拍照返回,onResume 被调用并尝试通过从SharedPreferences 获取适当的值来设置自定义对象的图像路径。由于那里没有对应的值,因此它将默认值 null 应用于imagePath

更新:我的程序的布局是ActivityA 主机FragmentA 托管这个DialogFragment 你在下面看到。用户按下FragmentA 中的按钮拍照,一旦他们拍照,在onActivityResult 我将图像路径设置为自定义对象中的字符串变量,并通过调用Log.d(mObject.getImagePath(), ...) 验证它是否存在.

然后他们可以再次按下相同的图片按钮来查看图像。这是NullPointerException 出现的地方。虽然我验证了图像路径存在于onActivityResult 中,但稍后当我尝试访问它时它会返回 null。这就是为什么BitmapFactory.decodeFile() 返回null- 因为imagePathFragmentA 中为null,当然当我尝试将它作为DialogFragment 中的额外访问时它会为null。

即使我验证它存在于onActivityResult 并将其分配给我的对象,任何人都可以看到为什么图像路径返回 null 吗?我不知道为什么会这样。我有一个类似的按钮,用户可以在其中输入文本,然后再次按下该按钮以在对话框中查看/编辑该文本。我按照相同的过程将变量分配给onActivityResult中的对象,我没有问题。

注意:如果您想查看照片是如何拍摄和保存的,请参考this 的回答,或按照右侧链接的问题进行操作。

imagePath:

/data/data/myPackageName/files/myInternalPicturesDir/IMG_20141011_152840.jpg.

FragmentA:

    //onCreateView
    mImageButton = (Button) v.findViewById(R.id.imageButton);
    mImageButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isImageButtonFirstClick)
            {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                imageUri = CameraUtils.getOutputMediaFileUri(CameraUtils.MEDIA_TYPE_IMAGE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                startActivityForResult(intent, REQUEST_IMAGE);
            }
            else
            {
                try
                {
                    Log.d("mImageButton onClick", mMyObject.getImagePath());
                    //returns null...
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }

                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputImageFragment dialog = InputImageFragment.newInstance(mMyObject.getImagePath());
                dialog.show(fm, DIALOG_IMAGE);
            }
        }
    });

...

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (resultCode != Activity.RESULT_OK)
    {
        return;
    }
    ...
    else if (requestCode == REQUEST_IMAGE)
    {
        String pathToInternallyStoredImage = CameraUtils.saveToInternalStorage(getActivity(), imageUri);
        mMyObject.setImagePath(pathToInternallyStoredImage);

        //verify imagePath exists, both return correct path
        Log.d("onActivityResult pathToInternallyStoredImage", pathToInternallyStoredImage);
        Log.d("onActivityResult mMyObject.getImagePath", mMyObject.getImagePath());

        isImageButtonFirstClick = false;
        preferences.edit().putBoolean("isImageButtonFirstClick", isImageButtonFirstClick).commit();
    }

DialogFragment:

public static InputImageFragment newInstance(String imagePath)
{
    Bundle args = new Bundle();
    args.putSerializable(EXTRA_IMAGEPATH, imagePath);

    InputImageFragment fragment = new InputImageFragment();
    fragment.setArguments(args);

    return fragment;
}

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    String imagePath = (String) getArguments.getSerializable(EXTRA_IMAGEPATH);

    try
    {
        Log.d("onCreateDialog imagePath", imagePath);
        //returns null...
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

    View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_input_image, null);

    final ImageView imageView = (ImageView) v.findViewById(R.id.dialogInputImageView);
    Bitmap image = BitmapFactory.decodeFile(imagePath);
    imageView.setImageBitmap(image);

    return new AlertDialog.Builder(getActivity())
            .setView(v)
            .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int whichButton)
                {
                    dialog.cancel();
                }
            })
            .create();
}

}

这会返回一个NullPointerException,根据我对BitmapFactory 的阅读,这要么是因为文件名为空,要么无法解码为位图。

10-13 17:10:39.498 5330-5330/myPackageName E/BitmapFactory﹕ Unable to decode stream: java.lang.NullPointerException

显示对话框,但它只是一个带有OK 按钮的空框。

我读过类似的问题,问题是ImageView 本身为空。我不认为这是这里的问题,但下面是 XML dialog_input_image。我尝试过修改 XML,并且我将 ImageView 作为 FrameLayout 的子代,类似于我见过的其他示例,但我得到了同样的错误。

<?xml version="1.0" encoding="utf-8"?>

<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dialogInputImageView"
    android:orientation="vertical"
    android:scaleType="centerInside"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
</ImageView>

我是 Android 新手,所以我不确定我哪里出错了。任何帮助表示赞赏,谢谢!

【问题讨论】:

  • inflatingonCreateView 中的布局在哪里
  • @kaushik 因为这是DialogFragment,所以我不打电话给onCreateView。我在onCreateDialog 中填充布局,然后在返回新的AlertDialog.Builder 时调用setView(v)
  • BitmapFactory.decodeFile返回的Bitmap是否为空?为这个异常附加 logcat 肯定会有所帮助。
  • 据我所知,问题可能出在此处:String imagePath = (String) getArguments().getSerializable(EXTRA_IMAGEPATH);: 1) 你在哪里以及如何将图像路径传递给片段? 2)如果这是一个简单的路径(字符串),你为什么使用Serializable
  • @MichaelKrause 当我调用decodeFile 时,logcat 只显示那一行。 @shoerat 请看主帖,我添加了更多代码。

标签: android bitmap imageview bitmapfactory


【解决方案1】:

问题与BitmapFactory.decodeFile() 无关。

问题是当用户去拍照时,会调用onPause。它检查是否存在现有图像路径,如果存在,则将其保存到SharedPreferences。用户第一次打开应用程序时,将不存在图像路径,因此不会保存任何内容。拍照后,onResume 被调用并尝试从SharedPreferences 检索图像路径,但最终分配了默认值null,因为不存在图像路径。我一直在使用boolean 来跟踪何时检索onResume 中的信息,但更好的解决方案是在尝试检索之前检查该值是否为null

    if (preferences.getString("imagePath", null) != null)
    {
        myObject.setImagePath(preferences.getString("imagePath", null));
    }

假设图像路径已经存在,原始代码会起作用。但它不会在第一次工作。

对于造成的混乱,我深表歉意,并感谢所有试图提供帮助的人。尽管问题与您的答案无关(这是我的错),但您的答案仍然很有帮助,我会在继续学习的过程中实施它们。

【讨论】:

    【解决方案2】:

    您最好使用Context 方法getFilesDir() 从您的内部存储中读取,例如:

    String image path = getFilesDir() .getAbsolutePath(); + "/myInternalPicturesDir/IMG_20141011_152840.jpg";
    final ImageView imageView = (ImageView) v.findViewById(R.id.dialogInputImageView);
    Bitmap image = BitmapFactory.decodeFile(imagePath);
    imageView.setImageBitmap(image);
    

    【讨论】:

    • 感谢您的回复。从我的DialogFragment 调用getActivity().getFilesDir().getAbsolutePath(); 只会返回/data/data/myPackageName/files。结果imagePathString不会还是一样吗?
    • 你能在你的帖子中添加完整的堆栈跟踪吗?
    • 当然。这就是它所显示的全部内容:10-11 16:35:56.098 31000-31000/myPackageName E/BitmapFactory﹕ Unable to decode stream: java.lang.NullPointerException
    • 不,每次我收到错误时,它只是一行。它周围唯一出现的其他内容是我自己的 Log.d 消息。
    • myInternalPicturesDir 已由您的应用创建?
    【解决方案3】:

    在将 Uri 更改为位图之前,首先从下面的代码中获取其路径,然后进行设置

    ..........
    Bitmap image = BitmapFactory.decodeFile(getRealPathFromURI(URI));
    }
    
    public String getRealPathFromURI(Uri contentURI) throws Exception {
        String result;
        Cursor cursor = context.getContentResolver().query(contentURI, null,
                null, null, null);
        if (cursor == null) { 
            result = contentURI.getPath();
        } else {
            cursor.moveToFirst();
            int idx = cursor
                    .getColumnIndex(MediaStore.Images.ImageColumns.DATA);
            result = cursor.getString(idx);
            cursor.close();
        }
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-19
      • 2020-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多