【问题标题】:Android, NullPointerException in an Adapter's getViewAndroid,适配器的 getView 中的 NullPointerException
【发布时间】:2016-08-20 20:26:21
【问题描述】:

我目前正在学习 Android,这是我第一次练习的应用程序之一。

该应用是“每日自拍”应用。它应该在屏幕上显示项目列表。每个项目都应该有一个图像的缩略图和文件名。单击一个项目应全屏打开图像。操作栏中有一个相机图标。单击此按钮应在设备上打开现有的相机活动。拍摄照片时,应保存该照片,然后显示在我的应用程序的列表中。

我已经完成了上述所有工作。但是我对这种场景有一个问题:我通过我的应用程序打开相机活动,然后将设备横向旋转,然后拍照,然后接受图片。当它尝试使用项目列表再次加载我的应用程序时,我得到了 NullPointerException。

我已经为适配器设置了断点并发现了这一点:适配器中的项目列表在那里,可以说大小为 10。前 9 个元素已填充且正常,但最后一个元素为空。如果我在相机打开时不旋转设备,我没有这个问题。

请问有什么办法解决这个问题吗?

这是我认为与问题相关的代码(我省略了一些东西,比如设置警报和上下文菜单,我认为它们在这里无关紧要?)。

在 MainActivity.java 中:

    private File mCurrentPhoto;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mAdapter = new SelfieListAdapter(getApplicationContext());
        setListAdapter(mAdapter);
        readImages();
        getListView().setBackgroundColor(getResources().getColor(R.color.white));

        setupAlarm();
        registerForContextMenu(getListView());
    }


    private void readImages(){
        File dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        for(File f : dir.listFiles()){
            mAdapter.add(f);
        }
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem menuItem){
        if(menuItem.getItemId() == R.id.camera_item){
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

            if(intent.resolveActivity(getPackageManager()) != null){
                getOutputMediaFile(); //Sets mCurrentPhoto to a new file with a unique name
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mCurrentPhoto));
                startActivityForResult(intent, CAMERA_REQUEST_CODE);
            }
        }
        return true;
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data){
        if(requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK){
            mAdapter.add(mCurrentPhoto);
        }
    }


    private void getOutputMediaFile(){
        if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            return;
        }

        File mediaStorageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!mediaStorageDir.exists()){
            if (!mediaStorageDir.mkdirs()){
                Log.d("DailySelfie", "Failed to create directory");
                return;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        mCurrentPhoto = new File(mediaStorageDir.getPath() + File.separator +
                "IMG_"+ timeStamp + ".jpg");
    }

这是适配器中的相关代码:

private static final int THUMBNAIL_WIDTH = 160;
    private static final int THUMBNAIL_HEIGHT = 120;
    List<File> mItems = new ArrayList<>();
    Context context;

    public SelfieListAdapter(Context context){
        this.context = context;
    }

    public void add(File file){
        mItems.add(file);
        notifyDataSetChanged();
    }

    @Override
    public View getView(int pos, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;

        if(convertView == null){
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(R.layout.selfie, parent, false);

            viewHolder = new ViewHolder();
            viewHolder.thumbnail = (ImageView) convertView.findViewById(R.id.thumbnail);
            viewHolder.filename = (TextView) convertView.findViewById(R.id.image_filename);

            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        File selfie = mItems.get(pos);

        Bitmap fullImage = BitmapFactory.decodeFile(selfie.getAbsolutePath());
        viewHolder.thumbnail.setImageBitmap(
                Bitmap.createScaledBitmap(fullImage, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, true));

        viewHolder.filename.setText(selfie.getName().split("\\.")[0]);
        return convertView;
    }

    static class ViewHolder{
        ImageView thumbnail;
        TextView filename;
    }

我得到的 NullPointerException 在这条线上,因为自拍为空:

Bitmap fullImage = BitmapFactory.decodeFile(selfie.getAbsolutePath());

但仅适用于列表中的最后一个元素。谢谢...感谢任何帮助。

顺便说一句,我在这里有什么明显的不良做法吗?

感谢您的帮助。

编辑:好的,我想我已经弄清楚为什么会发生这种情况,但我不知道如何解决它。 当设备倾斜时,我的活动是否被破坏然后重新创建?即使它不是当前的活动?所以mCurrentPhoto为null,所以我在onActivityResult中给适配器加了一个null?

我不知道如何解决这个问题。一个 null 意图仍然被传递到 onActivityResult 所以那里没有我可以使用的东西。

【问题讨论】:

    标签: java android listview android-adapter


    【解决方案1】:

    当您旋转 CameraActivity 并返回到 MainActivity 时,MainActivity 现在也处于新的方向。每当屏幕方向发生变化时,Activity 都会被销毁并重新创建,这就是 mCurrentPhoto 为 null 的原因。

    解决方案-

    1- 为您的 mCurrentPhoto 创建属性方法,如下所示

    private File getCurrentPhotoFile(){
      return mCurrentPhoto == null ? mCurrentPhoto = new File(mediaStorageDir.getPath() + File.separator +
                "IMG_"+ timeStamp + ".jpg") : mCurrentPhoto;
    }
    

    在你的 onActivityResult() 中使用这个

    mAdapter.add(getCurrentPhotoFile());
    

    或 2 - 使用 onSaveInstanceState() 回调方法保存 mCurrentPhoto 并在 onCreate() 或 onRestoreInstanceState() 上从包中获取 mCurrentPhoto 值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      相关资源
      最近更新 更多