Создание кастомного ListAdapter для вставки изображения и текста в ListView -5


Предисловие


На днях столкнулся с проблемой, нужно было запарсить большой объём данных из JSON и вывести все объекты в ListView.
Серди данных были ссылки на изображения, числовые данные и текст.


Изначально начал использовать SimpleAdapter, но вставлялся только текст, вместо картинки было пустое место.


Долго гуглил данную проблему, везде предлагалось то переводить в Bitmap, то ViewBinder и т.д. И было принято решение написать собственный Adapter наследуемый от ArrayAdapter.



Входные данные


При парсинге я получал данные:


  • 1. id (int)
  • 2. Name (String)
  • 3. Genres (String[])
  • 4. Tracks (int)
  • 5. Albums (int)
  • 6. Link (String)
  • 7. Decription (String)
  • 8. Cover (JSONObject) содержащий:
    small (String) и big (String)

В small и big содержатся ссылки на изображения каждого объекта.


В ListView нужно было вывести Имя (Name), Жанры (Genres), Количество песен и альбомов (Tracks+Albums) и картинку (Small). Все остальные данные нужны для подробного описания на втором экране.


Собираем данные


Так как мы не знаем количество получаемых объектов, то будем использовать отдельный ArrayList на каждое поле, чтобы потом передать это всё в наш CustomListAdapter.


Проходим в цикле по каждому JSONObject и получаем нужные нам данные:


Код из MainActivity
for (int i = 0; i < rootJSON.length(); i++) {
                    count++;
                    artist = rootJSON.getJSONObject(i);

                    name = artist.getString("name");
                    nameAr.add(count,name);

                    genresA = artist.getJSONArray("genres");
                    genres = "";
                    for (int j = 0; j < genresA.length(); j++) {
                            if (j==0) genres += genresA.getString(j);
                            else genres +=  ", " + genresA.getString(j) ;
                    }
                        genresAr.add(count,genres);

                    tracks = artist.getInt("tracks");
// проверка на написание слова "Песня" в зависимости от значения tracks, записываем нужное слово в строку TR

                   albums = artist.getInt("albums");
// проверка на написание слова "Альбом" в зависимости от значения albums, записываем нужное слово в строку AL
                   tracksAr.add(count,String.valueOf(albums)+al+", "+ String.valueOf(tracks)+tr);

                   cover = artist.getJSONObject("cover");
                   small = cover.getString("small");
                   smallAr.add(count,small);
}

Теперь приступим к самому главному, написанию нашего Адаптера. В него мы будем передавать context и все наши ArrayList.


Создаём новый класс CustomListAdapter:


CustomListAdapter.class

public class CustomListAdapter extends ArrayAdapter<String> {

    private final Activity context;
    private final ArrayList<String> nameAr,genresAr,tracksAr, smallAr;

    public CustomListAdapter(Activity context, ArrayList<String> nameAr, ArrayList<String> genresAr, ArrayList<String> tracksAr,ArrayList<String> smallAr) {
    }

    public View getView(int position,View view,ViewGroup parent) {
    }
}

В public CustomListAdapter мы должны определить поля класса:


Код CustomListAdapter
public CustomListAdapter(Activity context, ArrayList<String> nameAr, ArrayList<String> genresAr, ArrayList<String> tracksAr, ArrayList<String> smallAr) {
        super(context, R.layout.item, nameAr);

        this.context=context;
        this.nameAr=nameAr;
        this.genresAr=genresAr;
        this.tracksAr=tracksAr;
        this.smallAr=smallAr;
}

В public View getView мы должны написать что будет делать наш Адаптер. Для отображения элемента ListView создаём новый layout item.xml, в моём случае у меня в нём находятся ImageView и 3 TextView.


Код getView
public View getView(int position,View view,ViewGroup parent) {

        LayoutInflater inflater=context.getLayoutInflater();
        View rowView=inflater.inflate(R.layout.item, null,true);

        //устанавливаем тексты и картинку в элемент списка
        ImageView imageView = (ImageView) rowView.findViewById(R.id.imgSmall);
        TextView name = (TextView) rowView.findViewById(R.id.name);
        TextView genres = (TextView) rowView.findViewById(R.id.genres);
        TextView tracks = (TextView) rowView.findViewById(R.id.tracks);

        //загружаем картинку по ссылке, если картинка уже была загружена, берём её из кэша
        Picasso.with(context)
                .load(smallAr.get(position))
                .into(imageView);
        name.setText(nameAr.get(position));
        genres.setText(genresAr.get(position));
        tracks.setText(tracksAr.get(position));
        return rowView;
    }

И теперь нам остаётся в MainActivity вызвать наш Адаптер после того, как мы собрали все данные в массивы.


Вызов Адаптера
          artists = (ListView) findViewById(R.id.artistList);
          CustomListAdapter adapter = new CustomListAdapter(main, nameAr, genresAr, tracksAr, smallAr);
          artists.setAdapter(adapter);

Адаптер готов, можем запускать.


Скрин MainActivity

Весь проект доступен на GitHub: https://github.com/sergon146/Song


Для вставки изображений по URL использовал стороннюю библиотеку Picasso, она проста в использовании и при загрузке автоматически кэширует.




К сожалению, не доступен сервер mySQL