Использование CursorLoader с LoaderManager для извлечения изображений из приложений Android

На данный момент я использую getContentResolver().query()/managedQuery(), чтобы получить курсор для извлечения изображений из приложения галереи. Поскольку API, которые я использую, частично устарели, я хотел использовать CursorLoader с LoaderManager.

/**
 * Creates a cursor to access the content defined by the image uri for API
 * version 11 and newer.
 * 
 * @return The created cursor.
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private Cursor createCursorHoneycomb() {
    String[] projection = {
            MediaStore.Images.Media.DATA
    };
    Cursor cursor = getContentResolver().query(imageUri, projection, null, null, null);

    return cursor;
}

/**
 * Creates a cursor to access the content defined by the image uri from API
 * version 8 to 10.
 * 
 * @return The created cursor.
 */
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.FROYO)
private Cursor createCursorFroyo() {
    String[] projection = {
            MediaStore.Images.Media.DATA
    };
    Cursor cursor = managedQuery(imageUri, projection, null, null, null);

    return cursor;
}

Поскольку у меня нет ListView, я не использую никаких адаптеров. Я просто установил растровое изображение для ImageView.

/**
 * Sets the image bitmap for the image view.
 */
private void setupImageView() {
    String imagePath = getImagePathFromUri(imageUri);
    Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
    ImageView imageView = (ImageView) findViewById(R.id.image_view);

    imageView.setImageBitmap(bitmap);
}

/**
 * Returns an image path created from the supplied image uri.
 * 
 * @param imageUri The supplied image uri.
 * @return Returns the created image path.
 */
@SuppressWarnings("deprecation")
private String getImagePathFromUri(Uri imageUri) {
    Cursor cursor = null;
    String imagePath = null;

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        cursor = createCursorHoneycomb();
    } else {
        cursor = createCursorFroyo();
    }

    // if image is loaded from gallery
    if (cursor != null) {
        startManagingCursor(cursor);

        int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);

        cursor.moveToFirst();
        imagePath = cursor.getString(columnIndex);
    }
    // if image is loaded from file manager
    else {
        imagePath = imageUri.getPath();
    }

    return imagePath;
}

Можно ли использовать CursorLoader с LoaderManager для загрузки изображений из приложения галереи или файлового менеджера? Я не могу найти никакого решения.




Ответы (3)


Запустите менеджер загрузчика, вызвав getSupportLoaderManager, когда это необходимо.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_CODE) {
        if (resultCode == Activity.RESULT_OK) {
            imageUri = data.getData();
            getSupportLoaderManager().initLoader(0, null, this);
        } else if (resultCode == Activity.RESULT_CANCELED) {
            Toast.makeText(this, "Action canceled.", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(this, "Action failed!", Toast.LENGTH_LONG).show();
        }
    }
}

Затем создайте загрузчик курсора, который будет использоваться для получения пути к изображению.

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String[] projection = {
            MediaStore.Images.Media.DATA
    };
    CursorLoader cursorLoader = new CursorLoader(this, imageUri, projection, null, null, null);

    return cursorLoader;
}

Когда загрузчик курсора завершает работу, он использует полученные данные для обновления пользовательского интерфейса.

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    if (data != null) {
        int columnIndex = data.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);

        data.moveToFirst();
        imagePath = data.getString(columnIndex);
    } else {
        imagePath = imageUri.getPath();
    }

    setupImageView();
}

Это довольно легко сделать. Но мне нужно было понять, как использовать onCreateLoader() и onLoadFinished().

person Marcus Husar    schedule 20.01.2013
comment
Не могли бы вы поделиться со мной всем своим кодом здесь? Мне очень нужно сделать то же самое (но с MediaStore Audio) и что бы я ни делал, OnLoadFinished не вызывается. Заранее благодарю вас за вашу щедрость. - person dariusiv; 13.01.2014
comment
Постоянно рекомендуется изменить тип возвращаемого значения на CursorLoader в общедоступном Loader‹Cursor› onCreateLoader(int id, Bundle args). Пожалуйста, помогите мне. - person Rahul Upadhyay; 05.07.2014
comment
@dariusiv: Вы должны запустить загрузчик getLoaderManager().initLoader(<id>, <args>, <callback>), обычно getLoaderManager().initLoader(0, null, this). - person Marcus Husar; 15.09.2016

Вы можете заменить это

Cursor cursor = managedQuery(imageUri, projection, null, null, null);

с этим

CursorLoader cursorLoader = new CursorLoader(this, imageUri,
projection, null, null, null);
Cursor cursor = CursorLoader.loadInBackground();
person wekabelka    schedule 16.09.2015

Можно ли использовать CursorLoader с LoaderManager для загрузки изображений из приложения галереи или файлового менеджера?

Только если они публикуют, документируют и поддерживают ContentProvider.

person CommonsWare    schedule 20.01.2013
comment
Спасибо за ответ, CommonsWare. На данный момент я должен признать, что нет лучшего решения. Я постараюсь найти лучшее решение. - person Marcus Husar; 20.01.2013
comment
Наконец я нашел решение. Смотрите мой ответ ниже. - person Marcus Husar; 21.01.2013