Android Studio - помогите разобраться в этом коде - PullRequest
0 голосов
/ 10 ноября 2018

Я пытаюсь понять этот код:

private class ViewHolder {
    TextView txtName, txtSinger;
    ImageView playB, stopB;
}

@Override
public View getView(int position, View view, ViewGroup parent) {
    final ViewHolder viewHolder;
    if (view == null) {
        viewHolder = new ViewHolder();

        // inflate (create) another copy of our custom layout
        LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = layoutInflater.inflate(layout, null);


        viewHolder.txtName = (TextView) view.findViewById(R.id.songName_text);
        viewHolder.txtSinger = (TextView) view.findViewById(R.id.singer_text);
        viewHolder.playB = (ImageView) view.findViewById(R.id.play_png);
        viewHolder.stopB = (ImageView) view.findViewById(R.id.stop_png);
        view.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) view.getTag();
    }
    final Song song = arrayList.get(position);

    // make changes to our custom layout and its subviews
    viewHolder.txtName.setText(song.getName());
    viewHolder.txtSinger.setText(song.getSinger());

    // play music
    viewHolder.playB.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // MediaPlayer has not been initialized OR clicked song is not the currently loaded song
            if (currentSong == null || song != currentSong) {

                // Sets the currently loaded song
                currentSong = song;
                mediaPlayer = MediaPlayer.create(context, song.getSong());

                Toast.makeText(context, "Playing: "+ song.getSinger() + " " + song.getName(), Toast.LENGTH_LONG).show();
            }

            if (mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
                viewHolder.playB.setImageResource(R.drawable.play);
            } else {
                mediaPlayer.start();
                viewHolder.playB.setImageResource(R.drawable.pause);
            }
        }
    });

    // stop
    viewHolder.stopB.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            // If currently loaded song is set the MediaPlayer must be initialized
            if (currentSong != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                currentSong = null; // Set back currently loaded song
            }
            viewHolder.playB.setImageResource(R.drawable.play);
        }
    });
    return view;
}

Но не весь код!Часть, которая меня смущает, это ViewHolder часть.

Мои вопросы:

  • Почему я должен создать private class с именем ViewHolder вместо того, чтобы просто создать public method для хранения всех моих представлений (txtName, txtSinger, playB, stopB) и использовать это в моем inflater?
  • что означает view.setTag(viewHolder)?
  • Что именноsetTag и getTag в этом контексте?

Если кто-то может разбить это для меня, было бы очень полезно улучшить мое понимание кода.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

A viewholder - это шаблон проектирования, используемый в приложениях для Android для замены более дорогих вызовов findviewbyid.

Цитирование документов

Ваш код может часто вызывать findViewById() во время прокрутки ListView, что может снизить производительность. Даже когда адаптер возвращает раздутое представление для повторного использования, вам все равно нужно искать элементы и обновлять их. Способ обойти повторное использование findViewById() заключается в использовании шаблона проектирования "Держатель вида".

Относительно второго и третьего вопроса settag и gettag - это, по сути, способ, с помощью которого ваш взгляд может иметь «воспоминания», вы можете обратиться к здесь для получения дополнительной информации и более подробного объяснения!

Надеюсь, это поможет!

0 голосов
/ 10 ноября 2018

Что такое setTag и getTag в этом контексте?

Представления Android поддерживают «теги», которые представляют собой произвольные объекты, которые вы можете прикрепить к ним. Нет никакого реального определения для тегов, потому что они такие, какими вы хотите их видеть. Все они одинаково действительны:

  • view.setTag(2)
  • view.setTag("Hello world")
  • view.setTag(new Object())

что означает view.setTag (viewHolder)?

Вы присоединяете объект viewHolder к view в качестве его тега. Это не ничего не делает само по себе, но позволяет позже получить viewHolder, вызвав (ViewHolder) view.getTag().

Зачем мне создавать закрытый класс с именем ViewHolder [...]

Когда вы работаете с ListView адаптерами, есть две вещи, которые могут снизить производительность вашего приложения: вызов inflate() и findViewById().

Вы можете обойти первый, используя переданный аргумент view, когда он не равен нулю, и вызывая inflate(), только если переданный в view аргумент равен нулю. Вот этот бит вашего кода:

if (view == null) {
    ...
    LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = layoutInflater.inflate(layout, null);
    ...
} else {
    ...
}

Вы можете обойти второе, используя этот «шаблон ViewHolder». Вы создаете объект (держатель вида), чтобы "удерживать" виды после их поиска. Вот этот бит вашего кода:

final ViewHolder viewHolder;
if (view == null) {
    viewHolder = new ViewHolder();
    ...
    viewHolder.txtName = (TextView) view.findViewById(R.id.songName_text);
    viewHolder.txtSinger = (TextView) view.findViewById(R.id.singer_text);
    viewHolder.playB = (ImageView) view.findViewById(R.id.play_png);
    viewHolder.stopB = (ImageView) view.findViewById(R.id.stop_png);
    view.setTag(viewHolder);
} else {
    viewHolder = (ViewHolder) view.getTag();
}

Как только этот блок будет завершен, у вас будет ViewHolder экземпляр с именем viewHolder, который вы можете использовать для прямого доступа к представлениям. Если переданный аргумент view равен нулю, вы создаете держатель представления, заполняете , вызывая findViewById(), и сохраняете , вызывая setTag(). Если переданный аргумент view не равен нулю, вы можете просто получить держатель представления, вызвав getTag().

Соберите все это вместе, и это означает, что вы можете написать код следующим образом:

viewHolder.txtName.setText(song.getName());

Вместо этого более медленного кода:

TextView txtName = view.findViewById(R.id.songName_text);
txtName.setText(song.getName());
...