Created
May 2, 2017 07:41
-
-
Save RareScrap/6a2d076bb9c87ac22f3bdfb47e8ae529 to your computer and use it in GitHub Desktop.
Хорошие и плохие способы задания айдишников элементам RecyclerView
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.webtrust.tennosushi.adapters; | |
| import android.graphics.Bitmap; | |
| import android.graphics.BitmapFactory; | |
| import android.os.AsyncTask; | |
| import android.support.v7.widget.RecyclerView; | |
| import android.view.LayoutInflater; | |
| import android.view.View; | |
| import android.view.ViewGroup; | |
| import android.widget.ImageView; | |
| import android.widget.TextView; | |
| import com.webtrust.tennosushi.R; | |
| import com.webtrust.tennosushi.list_items.FoodItem; | |
| import java.io.InputStream; | |
| import java.net.HttpURLConnection; | |
| import java.net.URL; | |
| import java.util.HashMap; | |
| import java.util.List; | |
| import java.util.Map; | |
| /** | |
| * Адаптер для списка меню, основанный на {@link RecyclerView.Adapter<FoodItemRecyclerViewAdapter.ViewHolder>} | |
| * @author RareScrap | |
| */ | |
| public class FoodItemRecyclerViewAdapter extends RecyclerView.Adapter<FoodItemRecyclerViewAdapter.ViewHolder> { | |
| /** Слушатель MainActivity, регистрируемые для каждого элемента списка */ | |
| private final View.OnClickListener clickListener; | |
| /** Кэш для уже загруженных картинок (объектов Bitmap) */ | |
| private Map<String, Bitmap> bitmaps = new HashMap<>(); | |
| /** Список для хранения данных элементов RecyclerView */ | |
| private final List<FoodItem> items; | |
| public View latestView; // Нет, сохранять последний показанны View не имеет смысла | |
| /* | |
| И нет, задавать ID через статик переменную тоже не нужно | |
| Для этого в onBindViewHolder() есть position. Использование своей переменной приведет к тому, | |
| что после назажатия Back и возвращения к FoodListFragment, собъется нумерация ID'шников | |
| */ | |
| public static int i = 0; | |
| /** | |
| * Конструктор, инициализирующий свои поля. | |
| * @param items Набор элементов {@link FoodItem}, представляющий | |
| * собой входные данные, которые необходимо отобразить | |
| * @param clickListener Слушатель, который регистрирется для каждого элемента списка | |
| */ | |
| public FoodItemRecyclerViewAdapter(List<FoodItem> items, View.OnClickListener clickListener) { | |
| this.items = items; | |
| this.clickListener = clickListener; | |
| } | |
| /** | |
| * Вложенный субкласс {@link RecyclerView.ViewHolder}. Используется для | |
| * реализации паттерна View-Holder в контексте RecyclerView-логики | |
| * повторного использования представлений. | |
| */ | |
| public static class ViewHolder extends RecyclerView.ViewHolder { | |
| /** Ссылка на элемент GUI, представляющий название блюда */ | |
| public final TextView nameTextView; | |
| /** Ссылка на элемент GUI, представляющий состав блюда */ | |
| public final TextView componentsTextView; | |
| /** Ссылка на элемент GUI, представляющий цену блюда */ | |
| public final TextView priceTextView; | |
| /** Ссылка на элемент GUI, представляющий картинку блюда */ | |
| public final ImageView foodImageView; | |
| /** | |
| * Конструктор, инициализирующий свои поля. | |
| * @param itemView Представление одного элемента списка | |
| * @param clickListener Слушатель для этого элемента | |
| */ | |
| public ViewHolder(View itemView, View.OnClickListener clickListener) { | |
| super(itemView); | |
| // Получение ссылок на элементы GUI в представлении | |
| nameTextView = (TextView) itemView.findViewById(R.id.menu_text_card); | |
| componentsTextView = (TextView) itemView.findViewById(R.id.components_card); | |
| priceTextView = (TextView) itemView.findViewById(R.id.price_card); | |
| foodImageView = (ImageView) itemView.findViewById(R.id.menu_image_card); | |
| // Связывание слушателя с itemView | |
| itemView.setOnClickListener(clickListener); | |
| } | |
| } | |
| // TODO: Нихера не понял где что "упаковывается". Разобраться | |
| /** | |
| * Создает новый элемент списка и его объект ViewHolder. | |
| * | |
| * <p> | |
| * Компонент RecyclerView вызывает метод onCreateViewHolder | |
| * своего объекта RecyclerView.Adapter для | |
| * заполнения макета каждого элемента RecyclerView | |
| * и упаковки его в объект субкласса RecyclerView.ViewHolder с именем ViewHolder. | |
| * Новый объект ViewHolder возвращается RecyclerView для отображения. | |
| * </p> | |
| * | |
| * @param parent Объект субкласса {@link RecyclerView.ViewHolder} с представлениями View, | |
| * в которых будут отображаться данные. | |
| * @param viewType Значение int, представляющее позицию элемента в списке {@link RecyclerView}. | |
| * @return Объект, отображающий данные в виде GUI-элемента списка. | |
| */ | |
| @Override | |
| public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { | |
| //ViewHolder.menuTextView = (TextView) convertView.findViewById(R.id.menu_text); | |
| // Заполнение макета list_item | |
| View view = LayoutInflater.from( parent.getContext() ).inflate(R.layout.food_card_list_item, parent, false); | |
| // Плохая идея назначать вьюшкам ID ЗДЕСЬ и через setID() | |
| //latestView = view; | |
| //view.setId(i++); | |
| // Создание ViewHolder для текущего элемента | |
| return (new ViewHolder(view, clickListener)); | |
| } | |
| /** | |
| * Назначает данные элементам GUI. | |
| * @param holder Объект GUI, содеращий поля, которые следует установить | |
| * @param position Порядковый номер элемента {@link FoodItem}, который | |
| * хранится в {@link FoodItemRecyclerViewAdapter#items} | |
| */ | |
| @Override | |
| public void onBindViewHolder(ViewHolder holder, int position) { | |
| // Получение объекта FoodItem для заданной позиции ListView | |
| FoodItem foodItem = items.get(position); | |
| // Еще плохая идея - ограничиать присваивание ID'шников количеством элементов в списке | |
| // при юзании своей переменной i. Это приведет к тому, что после нажатии на кнопку назад | |
| // и возвратившись к середине списка, нумерация ID'шников начнется с 0 (при условии, что i | |
| // обнуляется при каждом закрытии фрагмента FoodListFragment где-то с серединного элемента списка. | |
| //if (i < 11) { | |
| holder.itemView.setTag(i++); | |
| //} | |
| // Присвоении ID к View на основании его порядкого номера в списке | |
| // Едиственно вернвый вариант | |
| holder.itemView.setTag(position); | |
| // Нецензурый способ проверить верность расставленных айдишников (при юзании | |
| // своей переменной i гарантированно крашит прогу) | |
| if (Integer.parseInt( holder.itemView.getTag().toString() ) != position) { | |
| // все пошло по пизде | |
| throw new NullPointerException("pizda"); | |
| } | |
| // Назначения текста элементам GUI | |
| holder.nameTextView.setText(foodItem.name); | |
| holder.componentsTextView.setText(foodItem.components); | |
| holder.priceTextView.setText( String.valueOf(foodItem.price) ); | |
| // Если картинка уже загружена, использовать ее; в противном случае загрузить в отдельном потоке | |
| if (bitmaps.containsKey(foodItem.picURL)) { | |
| // Дебажный кусок кода для отладчика | |
| /*String a1 = foodItem.picURL; | |
| Bitmap a2 = bitmaps.get(a1); | |
| holder.foodImageView.setImageBitmap(a2);*/ | |
| holder.foodImageView.setImageBitmap(bitmaps.get( foodItem.picURL )); | |
| }else { // Загрузить и вывести значок погодных условий | |
| new LoadImageTask(holder.foodImageView).execute(foodItem.picURL); | |
| } | |
| } | |
| /** | |
| * Возвращение количества элементов, связываемых через адаптер. | |
| * @return Количества элементов, связываемых через адаптер | |
| */ | |
| @Override | |
| public int getItemCount() { | |
| return items.size(); | |
| } | |
| // Кажись, изменение imageView так же изменяет и аргумент, переданный в конструкторе LoadImageTask(). Таким образом, создается нечно вроде "ссылки" | |
| // AsyncTask для загрузки изображения в отдельном потоке | |
| /** | |
| * Внутренний класс {@link AsyncTask}, предназначенный | |
| * для загрузки изображения в отдельном потоке | |
| * @author RareScrap | |
| */ | |
| private class LoadImageTask extends AsyncTask<String, Void, Bitmap> { | |
| /** Сохраненная ссылка на {@link ImageView} для вывода изображения */ | |
| private ImageView imageView; | |
| /** | |
| * Конструктор, инициализирующий свои поля. | |
| * Сохраняет ссылку на ImageView, куда следует поместить загруженный объект Bitmap. | |
| * @param imageView Ссылка наImageView, куда следует поместить загруженный объект Bitmap. | |
| */ | |
| public LoadImageTask(ImageView imageView) { | |
| this.imageView = imageView; | |
| } | |
| /** | |
| * Загрузить изображение с данного URL адреса. | |
| * @param params URL-адрес изображения | |
| * @return Загруженное изображение | |
| */ | |
| @Override | |
| protected Bitmap doInBackground(String... params) { | |
| Bitmap bitmap = null; | |
| HttpURLConnection connection = null; | |
| try { | |
| URL url = new URL(params[0]); // Создать URL для изображения | |
| // Открыть объект HttpURLConnection, получить InputStream и загрузить изображение | |
| connection = (HttpURLConnection) url.openConnection(); // Преобразование типа необходимо, потому что метод возвращает URLConnection | |
| try (InputStream inputStream = connection.getInputStream()) { | |
| bitmap = BitmapFactory.decodeStream(inputStream); | |
| bitmaps.put(params[0], bitmap); // Кэширование | |
| } | |
| catch (Exception e) { | |
| e.printStackTrace(); | |
| } | |
| } | |
| catch (Exception e) { | |
| e.printStackTrace(); | |
| } | |
| finally { // Этот участок кода будет выполняться независимо от того, какие исключения были возбуждены и перехвачены | |
| connection.disconnect(); // Закрыть HttpURLConnection | |
| } | |
| return bitmap; | |
| } | |
| // Выполняется в потоке GUI вроде как для вывода изображения | |
| /** | |
| * Связывает изображение с элементом списка. | |
| * @param bitmap Связываемое изображение | |
| */ | |
| @Override | |
| protected void onPostExecute(Bitmap bitmap) { | |
| imageView.setImageBitmap(bitmap); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment