相机意图后更新RecyclerView.Adapter

时间:2017-07-20 10:11:14

标签: java android android-recyclerview

目前,我正在使用相机意图捕获图像并在RecyclerView中更新它:

 private void cameraIntent() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                Log.e(TAG, ex.getLocalizedMessage());
            }

            if (photoFile != null) {
                Uri uri = FileProvider.getUriForFile(getActivity().getApplicationContext(),
                        "packagename.fileprovider",
                        photoFile);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
                startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
            }
        }
    }

在此之前发生的事情是它会触发我在setOnItemClickListener interface中创建的RecyclerView.Adapter的意图,该onCreatesetVisibleUserHint中调用以填充来自网络服务器的数据(或当if (isCamera) { cameraArray = object.getJSONArray(PROFILE_DETAILS_CAMERA_ARRAY_KEY); sortAdapter(true, object, cameraArray); } else { galleryArray = object.getJSONArray(PROFILE_DETAILS_GALLERY_ARRAY_KEY); sortAdapter(false, object, galleryArray); } 再次重新进入片段时触发)。

//初始化相机数据

cameraAdapter = new RecyclerViewAdapterGallery(getActivity(), array, true);
cameraAdapter.setOnItemClickListener(new RecyclerViewAdapterGallery.onItemClickListener() {
     @Override
     public void setOnItemClickListener(View view, final int position, String image, final boolean isCamera, boolean isLongClick) {
         clickResponse(view, position, image, isCamera, isLongClick, cameraAdapter, array, object);
     }
});
recyclerView.setAdapter(cameraAdapter);
cameraAdapter.notifyDataSetChanged();

//设置适配器

onActivityResult

帖子在@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_TAKE_PHOTO: if (resultCode != Activity.RESULT_CANCELED) { if (resultCode == Activity.RESULT_OK) { try { handleBigCameraPhoto(finalPosition); } catch (IOException e) { Log.e(TAG, e.getLocalizedMessage()); } } } break; ... } }

中发生了什么
private void handleBigCameraPhoto(int position) {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        getActivity().sendBroadcast(mediaScanIntent);
        saveFile(f, false, position);
}

handleBigCameraPhoto:

outState

这很好用,它可以很好地保存文件到Web服务器但是我想在成功时更新适配器,当然我无法使用inState或{{来恢复适配器对象1}}捆绑。

cameraArray.put(position, parseFile.getUrl());
userObject.put(PROFILE_DETAILS_CAMERA_ARRAY_KEY, cameraArray);
userObject.saveInBackground(new SaveCallback() {
           @Override
           public void done(ParseException e) {
                if (e == null) {
                     if (cameraAdapter != null) {
                         cameraAdapter.updatePosition(cameraArray, position);
                     }
                } else {
                     Log.e(TAG, "failed " + e.getLocalizedMessage());
                }
           }
});

到目前为止,我不确定为什么cameraAdapter没有更新,因为它没有返回null并且正在调用updatePosition()。

public void updatePosition(JSONArray array, int position) {
        Log.e(TAG, "updatePositionCalled");
        this.imageList = array;
        notifyItemChanged(position);
}

如果有人能帮助我解开这个谜团,那就太好了!此外,如果您需要更多代码或验证,请与我们联系。

注意:我目前拥有JSONArray个对象,位于适配器中的位置和存储在saveInstanceState包中的Web服务器对象,并且已正确恢复(因为当我从ViewPager片段中出来并返回,因此调用setUserVisibleHint它可以正确地从Web服务器恢复适配器。

更新:我在适配器中创建了一个getImageList()方法,并在假定的'更新'之后调用它,它更新列表值但不更新列表?!所以我真的认为问题出在notifyItemChanged(position)

 public JSONArray getImageList() {
        return imageList;
 }

//新来电

if (e == null) {
    cameraAdapter.updatePosition(cameraArray, position);
    Log.e(TAG, cameraAdapter.getImageList().toString());
} else {
    Log.e(TAG, "failed " + e.getLocalizedMessage());
}

它确实打印出列表中已传递给适配器的相应值,但似乎不更新UI。

更新II

我有两个(现已删除的)答案通知我notifyDataSetChanged(),这完全没有任何区别,并且会适得其反,因为它会在片段中重新绑定整个适配器,从而使其变慢。我已经用notifyItemChanged()重新定位专用位置(据称)。

注意事项II :我正在提供赏金,不是为了懒惰和未经研究的答案,但对于解决方案至少有一个解释,我想知道为什么会出错,所以我不再遇到同样的问题(不是快速修复)。我已经非常了解RecyclerViewRecyclerView.AdapterRecyclerView.ViewHolder的不同功能和组件,我只是遇到了Activity所在的特殊情况返回结果,但不按预期更新UI。

1 个答案:

答案 0 :(得分:4)

嘿,我认为问题是使用以下方法的行this.imageList = array

public void updatePosition(JSONArray array, int position) {
        Log.e(TAG, "updatePositionCalled");
        this.imageList = array;
        notifyItemChanged(position);
}

原因:

this.imageList = array创建新参考。它不会更新在Recyclerview中传递的旧引用。因此,notifyItemChanged(position);正在刷新视图,但是使用了尚未更新的数组的旧引用。

<强>解决方案:

您需要按以下方式更新方法:

public void updatePosition(String url, int position) {
        Log.e(TAG, "updatePositionCalled");
        this.imageList.put(position, url);
        notifyItemChanged(position);
}

userObject.put(PROFILE_DETAILS_CAMERA_ARRAY_KEY, cameraArray);
userObject.saveInBackground(new SaveCallback() {
           @Override
           public void done(ParseException e) {
                if (e == null) {
                     if (cameraAdapter != null) {
                         cameraAdapter.updatePosition(parseFile.getUrl(), position);
                     }
                } else {
                     Log.e(TAG, "failed " + e.getLocalizedMessage());
                }
           }
});

<强>更新

此外,将notifyItemChanged(position)替换为notifyItemInserted(position),因为数组中插入了新项目。