SQliteOpenHelper База данных indexoutofbounds при вызове из OnResume фрагмента - PullRequest
0 голосов
/ 29 сентября 2019

У меня проблема с SQliteDatabase / OpenHelper / AssetHelper, которую трудно исправить, поскольку я не могу воспроизвести ошибку, с которой сталкиваются многие пользователи моего приложения, на моих устройствах или на любых устройствах с эмуляцией Android Studio, поэтому этот кодчтобы показать, что вы работаете для меня, но не для некоторых других, и я не знаю почему.

Мои пользователи иногда получают indexoutofboundsexception (я полагаю), когда мое приложение принимает значение из List, которое заполняется из базы данных (в папке ресурсов). Так что, похоже, база данных не загружается должным образом. Проблема может быть связана с контекстом, который я передаю, когда я получаю экземпляр класса DatabaseAccess DBProgressAccess в OnResume обратном вызове жизненного цикла фрагмента.

Я не очень старался решить проблему только потому, что сбой случается так редко (только один раз на моем телефоне Android 6.0), но я получаю сообщения от Google о частых сбоях для других устройств Android (дов том числе и Android 6.0). Трассировка стека, которая у меня есть для сбоев, происходит из консоли разработчиков Google.

У меня есть фрагмент, который загружается при запуске приложения. В его showSets12() методе, вызванном из onResume() (где я вижу ошибку indexoutofbounds), я получаю доступ к базе данных оценок пользователей:

    private void showSets12()
    {
        DBProgressAccess dbProgressAccess = DBProgressAccess.getInstance(getActivity());
        dbProgressAccess.openUserProgressDb();
        dbProgressAccess.getDayValues();
        int scoreToday = dbProgressAccess.getScores().get(0); <--I think the error comes from this
        ...
        dbProgressAccess.closeUserProgressDb();

    }

В общедоступном классе DBProgressAccess у меня есть:

public class DBProgressAccess {

    private SQLiteOpenHelper openHelper;
    private SQLiteDatabase database;
    private static DBProgressAccess instance;

    private List<String> dates;
    private List<Integer> scores;
    private List<String> times;

    public static final String TABLE_NAME = "UserProgress";

    public List<Integer> getScores() {return scores;}


    private DBProgressAccess(Context context) {
        this.openHelper = new DBProgressHandler(context);
    }

    public static DBProgressAccess getInstance(Context context)
    {
        Log.d(TAG, "getInstance");
        if(instance == null) {
            instance = new DBProgressAccess(context);
        }
        return instance;
    }


    /**
     * Open the database connection.
     */
    public void openUserProgressDb() {
        Log.d(TAG, "openUserProgress");
        this.database = openHelper.getWritableDatabase();
    }


    /**
     * Is todays date included in the database? If not, create it and search the database to populate lists for times and scores
     */
    public void getDayValues()
    {
        if (checkIfDateExists()) {
            Cursor cursor = searchDayProgress();
            searchDatabase(cursor);
        }
        else
        {
            createDayEntry();
            Cursor cursor = searchDayProgress();
            searchDatabase(cursor);
        }
    }

    /**
     * Check to see if there is a record in the database for today 
     */
    public boolean checkIfDateExists()
    {
        Cursor cursor = searchDayProgress();
        if(cursor.getCount() <= 0)
        {
            cursor.close();
            return false;
        }
        cursor.close();
        return true;
    }


    /**
     * Insert todays date into the database
     */
    private void createDayEntry()
    {
        Date today = Calendar.getInstance().getTime();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String todayString = formatter.format(today);
        int score = 0;
        String time = "0:00:0";

        ContentValues cv = new ContentValues();
        cv.put("date", todayString);
        cv.put("score", score);
        cv.put("time", time);

        database.insert(TABLE_NAME, null, cv);
    }


    /**
     * Find the database record for today
     */
    private Cursor searchDayProgress() {
        String whereQuery = "SELECT * FROM UserProgress WHERE date = date('now')";
        Log.d(TAG, "searchWeekProgress " + whereQuery);
        return database.rawQuery(whereQuery, null);
    }

    /**
     * Populate lists of time, date and progress taken from the database
     */
    public void searchDatabase(Cursor cursor)
    {
        List<String> listDate = new ArrayList<>();
        List<Integer> listUserProgress = new ArrayList<>();
        List<String> listTime = new ArrayList<>();

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            listDate.add(cursor.getString(cursor.getColumnIndex("date")));
            listUserProgress.add(cursor.getInt(cursor.getColumnIndex("score")));
            listTime.add(cursor.getString(cursor.getColumnIndex("time")));
            cursor.moveToNext();
        }
        cursor.close();

        setDates(listDate);
        setScores(listUserProgress);
        setTimes(listTime);
    }

    private void setDates(List<String> dates) {this.dates = dates;}
    private void setScores(List<Integer> scores) {this.scores = scores;}
    private void setTimes(List<String> times) {this.times = times;}

}


Я считаю, что переменные List<string> оказываются пустыми.

Хотелось бы добавить более конкретный код, но трассировка стека консоли разработчика Google неясна.

ОшибкаЯ получаю это с консоли разработчиков Google, а не Android Studio, так как я не могу воспроизвести проблему на моих устройствах или любых эмулируемых устройствах.

java.lang.RuntimeException: 
  at android.app.ActivityThread.performResumeActivity (ActivityThread.java:3573)
   at android.app.ActivityThread.handleResumeActivity (ActivityThread.java:3613)
   at android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2862)
   at android.app.ActivityThread.-wrap12 (ActivityThread.java)
   at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1574)
   at android.os.Handler.dispatchMessage (Handler.java:110)
   at android.os.Looper.loop (Looper.java:203)
   at android.app.ActivityThread.main (ActivityThread.java:6364)
   at java.lang.reflect.Method.invoke (Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1076)
   at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:937)

Caused by: java.lang.IndexOutOfBoundsException: 
  at java.util.ArrayList.get (ArrayList.java:411)
  at org.ieltstutors.academicwordlist.AcademicWordListFragment.showSets12 (AcademicWordListFragment.java)
  at org.ieltstutors.academicwordlist.AcademicWordListFragment.access$000 (AcademicWordListFragment.java)
  or                     .access$200 (AcademicWordListFragment.java)
  or                     .drawCircularLockedProgress (AcademicWordListFragment.java)
  or                     .onCreateView (AcademicWordListFragment.java)
  or                     .openCloseSet (AcademicWordListFragment.java)
  or                     .showCircularScores (AcademicWordListFragment.java)
  or                     .showScores (AcademicWordListFragment.java)
  or                     .updateScores (AcademicWordListFragment.java)
  at org.ieltstutors.academicwordlist.AcademicWordListFragment.onResume (AcademicWordListFragment.java)

К сожалению, это вся информация об ошибке, которую я имею.

Таким образом, исключение IndexOutOfBoundsException происходит из showSets12. Может ли ошибка быть из-за неправильного контекста для getInstance? Или, может быть, от getWriteableDatabase? Почему к базе данных иногда можно обращаться правильно, а не в другой раз? Я помню, что когда приложение рухнуло на моем телефоне, когда оно запускалось, я сразу же попытался открыть приложение на телефоне моего друга, но он тоже рухнул, так как никогда раньше не падал ни на одном из них. Совпадение?

Любая помощь с благодарностью. Спасибо!

1 Ответ

0 голосов
/ 29 сентября 2019

Фрагменты onResume () или onPause () будут вызываться только при вызове Activity onResume () или onPause (). Они тесно связаны с деятельностью. если вы хотите что-то сделать, когда ваш фрагмент добавлен в действие, вы можете использовать OnAttach () или другие жизненные циклы фрагмента

Прочтите это, чтобы понять фрагмент Жизненный цикл

...