Разработка клиента для галереи LiveStreet

Разработка клиента для галереи LiveStreet

Наша студия уже давно разрабатывает плагины для популярной CMS LiveStreet, одним из которых является удобная и простая в использовании галерея. В рамках развития новых направлений, в качестве одного из первых приложений студией был разработан клиент для этого популярного плагина.

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

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