Подтвердить что ты не робот

Обновление RecyclerView.Adapter после намерения камеры

Итак, в настоящее время я беру изображение и обновляю его в 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, который вызывается в onCreate, для заполнения данных с веб-сервера (или при срабатывании 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);
}

//адаптеры настроек

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;
...
}

}

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);
}

Это прекрасно работает, он сохраняет файл на веб-сервере, но я хочу обновить адаптер, когда это будет успешным, и, конечно, я не могу восстановить объект адаптера с помощью outState или inState bundle.

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, и восстанавливается правильно (потому что, когда я выхожу из ViewPager и вернитесь, вызывая setUserVisibleHint, он правильно восстанавливает адаптер с веб-сервера).

Обновление. Я создал метод 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());
}

Он буквально печатает соответствующие значения в списке, который был передан адаптеру, но, похоже, не обновляет пользовательский интерфейс.

Обновление II:

У меня было два (теперь удаленных) ответа, которые советовали мне notifyDataSetChanged(), что не имеет никакого значения вообще и является контрпродуктивным, поскольку он будет перепроверять весь адаптер внутри фрагмента, что делает его медленным. Я уже перевязываю выделенное положение (предположительно) с помощью notifyItemChanged().

Примечание II. Я предлагаю щедрость не для ленивых и невосстановленных ответов, но для решения, по крайней мере, объяснения, я хотел бы знать почему это происходит не так, поэтому я снова не сталкиваюсь с той же проблемой (не быстрое решение). Я уже хорошо знаю различные функции и компоненты RecyclerView, RecyclerView.Adapter и RecyclerView.ViewHolder, у меня просто возникают проблемы в этом конкретном сценарии, когда Activity возвращает результат, но не обновляет UI, как и должно быть.

4b9b3361

Ответ 1

Эй, я думаю, что проблема связана с линией 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());
                }
           }
});

Update:

Кроме того, замените notifyItemChanged(position) на notifyItemInserted(position), поскольку новый элемент вставляется здесь в массив.