首页 > 解决方案 > 从片段的 OnResume 调用 SQliteOpenHelper 数据库 indexoutofbounds

问题描述

我的 SQliteDatabase/OpenHelper/AssetHelper 存在一个难以修复的问题,因为我无法复制我的许多应用程序用户在我的设备或任何 android studio 模拟设备上遇到的错误,所以我将向您展示这段代码对我有用,但对其他一些人不起作用,我不知道为什么。

当我的应用程序从数据库(在资产文件夹中)填充的值中获取值时,我的用户有时会得到indexoutofboundsexception(我相信)。List所以看起来数据库没有正确加载。当我在 Fragment 的生命周期回调中获取 DatabaseAccess 类DBProgressAccess的实例时,问题可能与我传递的上下文有关。OnResume

我没有尝试太多来解决这个问题,只是因为崩溃很少发生(在我的 android 6.0 手机上只有一次),但我从 google 收到关于其他 android 设备(直到并包括 android 6.0)频繁崩溃的报告. 我对崩溃的堆栈跟踪来自谷歌开发者控制台。

我有一个在应用程序启动时加载的片段。在它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>变量结果是空的。

我希望我可以输入更具体的代码,但谷歌开发控制台堆栈跟踪不清楚。

我得到的错误来自谷歌开发者控制台,而不是 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?为什么有时可以正确访问数据库,但有时不能正确访问数据库?我记得当应用程序启动时,当应用程序在我的手机上崩溃时,我立即尝试在我朋友的手机上打开该应用程序,但它也崩溃了,以前从未崩溃过。巧合?

任何帮助是极大的赞赏。谢谢!

标签: androiddatabasesqliteindexoutofboundsexception

解决方案


只有在调用活动 onResume() 或 onPause() 时才会调用片段 onResume() 或 onPause()。它们与 Activity 紧密耦合。如果您想在片段添加到活动时做某事,您可以使用 OnAttach() 或其他片段生命周期

阅读本文以了解片段生命周期


推荐阅读