Разработка клиента для галереи 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
для подгрузки миниатюр и использует свой кеш. Приложение интуитивно понятное в использовании. Мы надеемся, что оно будет полезным для вас.