在Camera Intent之后更新RecyclerView.Adapter

Bra*_*son 10 java android android-recyclerview

所以目前,我正在RecyclerView使用Camera Intent 捕获图像并更新它:

 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);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

在此之前发生的事情是它会触发setOnItemClickListener interface我在my RecyclerView.Adapter中创建的意图,该意图被调用onCreate以填充来自web服务器的数据(或者当setVisibleUserHint它们再次重新进入片段时被触发).

//初始摄像机数据

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);
}
Run Code Online (Sandbox Code Playgroud)

//设置适配器

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();
Run Code Online (Sandbox Code Playgroud)

帖子里面发生了什么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;
...
}

}
Run Code Online (Sandbox Code Playgroud)

handleBigCameraPhoto:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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());
                }
           }
});
Run Code Online (Sandbox Code Playgroud)

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

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

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

注意:我目前拥有JSONArray对象,适配器中的位置以及存储在saveInstanceStatebundle 中的web-server对象,并且可以正确恢复(因为当我从ViewPager片段中退出并重新进入时,因此调用setUserVisibleHint它从web恢复适配器 -服务器正确).

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

 public JSONArray getImageList() {
        return imageList;
 }
Run Code Online (Sandbox Code Playgroud)

//新来电

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

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

更新II:

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

注意二:我提供赏金,不是懒惰和未经研究的答案,但对于解决方案至少有一个解释,我想知道为什么它会出错,所以我不再遇到同样的问题(不是快速修复).我已经非常了解a的不同功能和组件RecyclerView,RecyclerView.Adapter而且RecyclerView.ViewHolder,我在这个Activity返回结果的特定场景中遇到了麻烦,但没有按原样更新UI.

iMD*_*oid 4

嘿,我认为问题出在下面的方法上 this.imageList = array

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

原因 :

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

解决方案:

您需要更新方法如下:

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

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());
                }
           }
});
Run Code Online (Sandbox Code Playgroud)

更新:

另外,替换notifyItemChanged(position)为,notifyItemInserted(position)因为新项目正在插入数组中。