ConcurrentModificationException, когда я не изменяю массив? - PullRequest
0 голосов
/ 10 февраля 2019

Я получаю java.util.ConcurrentModificationException , и я не знаю почему.

В Logcat он указывает на этот код, но я не вижу ничего, что могло бы вызватьa ConcurrentModificationException .

 private void initRecyclerView() {
    Main.musicList = Main.songs.songs;
    Log.d(TAG, "Main.musicList: " + String.valueOf(Main.musicList));
    if ((Main.musicList != null) && (!Main.musicList.isEmpty())) {
        // Connects the song list to an adapter
        // (Creates several Layouts from the song list)
        allSongsAdapter = new AllSongsAdapter(getActivity(), Main.musicList);

        final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());

        recyclerViewSongs.setLayoutManager(linearLayoutManager);
        recyclerViewSongs.setHasFixedSize(true);
        recyclerViewSongs.setAdapter(allSongsAdapter);
   }
}

Main.musicList является общедоступным статическим ArrayList musicList = null;в другом классе.

И Main.songs.songs - это публичный ArrayList songs = null;в моем классе, где я получаю все песни на устройстве и заполняю их arraylist.

в onDestroy я звоню:

musicList = null;

EDIT

Хорошо, я обнаружил проблему, когда я не вызываю onDestroy musicList = null, нет ConcurrentModificationException.

Но как мне разыменовать массив в onDestroy, чтобы он мог быть мусоромсобрано?

РЕДАКТИРОВАТЬ

Таким образом, проблема была не в вызове onDestroy, ошибка возникает, когда я открываю приложение, и в мои массивы попадают все песни, затем язакройте приложение и снова откройте его, а затем выдается исключение.

Как я заполняю массив песен

   songs = new ArrayList<>();

   // Columns retrieved from the system database (MediaStore.Audio.Media).
    String[] projection1 = {
            SONG_ID,
            SONG_TITLE,
            SONG_ARTIST,
            SONG_ALBUMID,
            SONG_ALBUM,
            SONG_FILEPATH,
            SONG_DURATION,
            SONG_YEAR,
    };
  // Limits results to only show MUSIC files.
    // It's a SQL "WHERE" clause - it becomes `WHERE IS_MUSIC NOT EQUALS ZERO`.
    final String musicsOnly = SONG_IS_MUSIC + "!=0";

    // Querying the Media DATABASE.
    cursor = resolver.query(musicUri, projection1, musicsOnly, null, null);
    try {
        if (cursor != null && cursor.moveToFirst()) {
            do {

                // Creating a SONG from the VALUES in each column.
                Song song = new Song(cursor.getLong(cursor.getColumnIndexOrThrow(SONG_ID)),
                        cursor.getString(cursor.getColumnIndexOrThrow(SONG_FILEPATH)));

                song.setTitle(cursor.getString(cursor.getColumnIndexOrThrow(SONG_TITLE)));
                song.setArtist(cursor.getString(cursor.getColumnIndexOrThrow(SONG_ARTIST)));
                song.setAlbumID(cursor.getLong(cursor.getColumnIndexOrThrow(SONG_ALBUMID)));
                song.setAlbum(cursor.getString(cursor.getColumnIndexOrThrow(SONG_ALBUM)));
                song.setDuration(cursor.getLong(cursor.getColumnIndexOrThrow(SONG_DURATION)));
                song.setYear(cursor.getInt(cursor.getColumnIndexOrThrow(SONG_YEAR)));

                // Using the previously created maps to add the current song GENRE.
                String currentGenreID = songIdToGenreIdMap.get(Long.toString(song.getId()));
                String currentGenreName = genreIdToGenreNameMap.get(currentGenreID);
                song.setGenre(currentGenreName);

                // Adding the Song to the global array list 'songs'.
                songs.add(song);
            } while (cursor.moveToNext());
        }
    }catch (Exception e){
        // Exception caught because no songs were found.
        Log.e(TAG, "Exception caught because no songs were found!", e);
        throw new Exception();
    }finally {
        if (cursor != null ){
            cursor.close();
        }
    }

1 Ответ

0 голосов
/ 10 февраля 2019

Это подход высокого уровня, который позволит GC правильно очистить вашу память.

Внутри вашего Activity члена определения класса:

private List<Song> mMySongs;

В методе onCreate выinit RecyclerView и затем читать песни в массив:

// getSongs is your models method where you read the songs and return them as array
mMySongs = getSongs();
// Enter code to create the adapter and set it for RecyclerView

Теперь, когда вы используете сильную ссылку вместо статической, когда ваш Activity уничтожен, GC может очистить память и когда выПерезапустите Activity, он снова запросит песни.

...