Android: RecyclerView `getChildAt ()` возвращает ноль, даже когда объект находится на экране - PullRequest
0 голосов
/ 16 января 2019

У меня есть активность Android, которая содержит RecyclerView, в основном я создаю приложение для музыкального плеера. Здесь предыдущая кнопка песни должна найти предыдущий элемент RecyclerView и выполнить щелчок по нему (это будет играть песню), для этого, когда я использую recyclerView.getChildAt(), она возвращает ноль, что приводит к ошибке.

Вот код для onClickListener предыдущей кнопки ...

prevSong_bottomSheet.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // We start by checking if this is the first song or not!
            if (songIndex.getCurrentIndex() == 0) {
                Toast.makeText(MainActivity.this, "Nothing to play before this", Toast.LENGTH_SHORT).show();

                // Now, this simply return as we don't want to execute any of the following code!
                return;
            }

            Log.d(DEBUG_MESSAGE, "Original song index: " + songIndex.getCurrentIndex());

            try {
                // First, as we know that we'll be playing the previous audio, we start by decrementing
                //  the value inside `SongIndex`.
                songIndex.prevSongPlayed();

                // As the value inside `SongIndex` has been decremented, we use the same here!
                View parentView = recyclerView.getChildAt(songIndex.getCurrentIndex());
                // Now we extract the action button associated with this particular view!
                Button tempButton = parentView.findViewById(R.id.music_actionButton);

                // Now that we've got the button, instead of calling `startSong()` directly, we'll
                //  perform a click on the button, this way if we decide to perform some other action (in the future)
                //  once the user clicks that button, the action would still be valid!
                tempButton.performClick();
                Log.d(DEBUG_MESSAGE, "Previous song played successfully!");
            } catch (NullPointerException e) {
                // Lastly, if any error occurred in the above code, in the first line itself, we
                //  have already decremented SongIndex in the first line itself, thus, we increment
                //  it here to balance it out!
                //songIndex.nextSongPlayed();
                Log.d(DEBUG_MESSAGE, e.getLocalizedMessage() + "\n\n\n\n\n\n");
                e.printStackTrace();

                Log.d(DEBUG_MESSAGE, "Final song index: " + songIndex.getCurrentIndex());

            }
        }
    });

Во время выполнения вышеуказанного кода он работает отлично, пока следующий элемент RecyclerView находится на экране, однако начинает возвращать ноль, когда представление находится за пределами экрана!

Да, я знаю, что RecyclerView уничтожит элементы, находящиеся за пределами экрана (или даже не создаст их). Чтобы обойти это, я попытался использовать recyclerView.scrollToPosition(), даже после этого он возвращает ноль. Я попытался прокрутить вверх до позиции предыдущего элемента и даже на 2 или 3 позиции над ним, но getChildAt() возвращает ноль. Помимо этого, я также пытался заблокировать основной поток, чтобы дождаться прокрутки RecyclerView вверх (используя бесконечный цикл), даже после того, как getChildAt() вернет ноль.

Как мне решить эту проблему?

P.S. songIndex - это класс, который должен следить за положением песни, которая воспроизводится в данный момент. Вот код для этого (на всякий случай):

private class SongIndex {
    /**
     * This class is used to keep a track as to which song is being played currently, the data member
     * created inside this class would be regularly updated using the functions defined below!
     * Thus, this class will be used at various instances inside the program to know about the
     * index of the song (inside the RecyclerView) which is being played currently!
     */

    private int currentSongIndex;

    public int getCurrentIndex() {
        return currentSongIndex;
    }

    public void setCurrentSongIndex(int currentSongIndex) {
        this.currentSongIndex = currentSongIndex;
    }

    public void nextSongPlayed() {
        currentSongIndex++;
    }

    public void prevSongPlayed() {
        currentSongIndex--;
    }
}

PSS Еще одна вещь, которую я пытался решить, заключалась в том, что, когда я достиг верхней части экрана (над ними было бы больше элементов, но ни один из них не был бы на экране, то есть RecyclerView, вероятно, уничтожил бы их), после этого я прокручивал вручную, чтобы текущая воспроизводимая песня была в середине экрана (теперь у нее есть элементы над ней), даже сейчас, когда я попробовал предыдущую кнопку, я все равно каким-то образом оказался внутри catch часть: (

1 Ответ

0 голосов
/ 16 января 2019

В соответствии с кодом, которым вы поделились, currentSongIndex не инициализируется.У него будет какое-то значение мусора, поэтому ваше условие if (songIndex.getCurrentIndex () == 0) будет ложно в первый раз, а songIndex.getCurrentIndex () вернет мусор, следовательно recyclerView.getChildAt (songIndex.getCurrentIndex ());будет нулевым

...