Розробка клієнта для галереї LiveStreet

Наша студія вже давно розробляє плагіни для популярної CMS LiveStreet, одним із яких є зручна та проста у використанні галерея. У рамках розвитку нових напрямків, як одне з перших додатків, студією був розроблений клієнт для цього популярного плагіна.
Задача полягала в тому, щоб розробити клієнт-додаток, який дозволить користувачеві переглядати всі графічні файли на його пристрої, за бажанням сфотографувати новий, відзначити їх для додавання в галерею та відправити на сервер.

Основною проблемою був вивід зображень користувача у вигляді скролюючого альбому. З допомогою MediaStore.Images ми отримали мініатюри всіх зображень, які є на пристрої, і це не виявилося великою проблемою. Але коли ми намагалися використовувати GridView зі стандартним адаптером, то зіткнулися з тим, що прокрутка сильно «тормозила». Як виявилося, затримки проявляються при підгрузці мініатюр в головному потоці. Ми пробували тягнути прев'ю в AsyncTask, що частково допомогло. Але прокрутка все одно йшла ривками.
Маючи досвід підгрузки картинок в ListView з сервера, ми вирішили піти тим же шляхом, використовуючи бібліотеку Universal Image Loader.
Після підключення бібліотеки в класі, успадкованому від Application, налаштовуємо ImageLoader. Після проведення кількох тестів було вирішено використовувати стандартні налаштування:
ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(getApplicationContext()));
Далі налаштовуємо опції відображення:
public static DisplayImageOptions options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.empy_photo)
.resetViewBeforeLoading()
.cacheInMemory()
.cacheOnDisc()
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
.build();Опишу детальніше:
showStubImage(R.drawable.empy_photo)— зображення, яке буде відображатися до завантаження або в разі невдалої загрузки.resetViewBeforeLoading()— обнуляти вьюху перед завантаженням нового зображення.cacheInMemory()— кешування в оперативній пам'яті.cacheOnDisc()— кешування у внутрішній пам'яті.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)— декодувати зображення максимально швидко (ImageScaleType.POWER_OF_2) або максимально економно для оперативної пам'яті (ImageScaleType.EXACT).
Тепер можна використовувати ImageLoader в адаптері:
ImageLoader.getInstance().displayImage(item.thumbUri.toString(), holder.imageview, LsGalleryApp.options);
Після цього проблема з прокруткою ривками була вирішена, але з'явилася нова — тумбики після прокрутки занадто довго завантажувалися. Як виявилося, все діло в отриманні id зображень з MediaStore. Найвдаліший спосіб вирішення — отримати всі id під час завантаження програми. Для цього був написаний невеличкий AsyncTask:
private class GetImageTask extends AsyncTask{ String message; ProgressDialog dialog; public GetImageTask(String message) { this.message = message; this.dialog = new ProgressDialog(context); } @Override protected Void doInBackground(Void... params) { externalContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; String[] projection = {}; String selection = ""; String[] selectionArgs = null; externalCursor = getContentResolver().query(externalContentUri , projection, selection, selectionArgs, null); externalColumnIndex = externalCursor.getColumnIndex(MediaStore.Images.Media._ID); imageAdapter = new ImageAdapter(context, callback_click_image); imageAdapter.initialized(); return null; } @Override protected void onPreExecute() { dialog.setMessage(message); dialog.setIndeterminate(true); dialog.setCancelable(false); dialog.show(); } @Override protected void onPostExecute(Void result) { SetGridView(); if (dialog.isShowing()) dialog.dismiss(); } }
Для отримання прев'юшки в адаптері використовуємо таку функцію:
protected Uri getThumbUri(Uri original) {
String uri = "";
Cursor cursor = MediaStore.Images.Thumbnails.queryMiniThumbnail(
mContext.getContentResolver(), Long.valueOf(original.getLastPathSegment()),
MediaStore.Images.Thumbnails.MINI_KIND,
null);
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
uri = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Thumbnails._ID));
cursor.close();
Uri thumb = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, uri);
return thumb;
} else return null;
}В результаті за допомогою Universal Image Loader ми маємо чудово оптимізовану галерею, яка використовує AsyncTask для підвантаження мініатюр і має свій кеш. Додаток інтуїтивно зрозуміле у використанні. Сподіваємося, що воно буде корисним для вас.


