Розробка клієнта для галереї 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 для підвантаження мініатюр і має свій кеш. Додаток інтуїтивно зрозуміле у використанні. Сподіваємося, що воно буде корисним для вас.