У меня проблема с 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
? Почему к базе данных иногда можно обращаться правильно, а не в другой раз? Я помню, что когда приложение рухнуло на моем телефоне, когда оно запускалось, я сразу же попытался открыть приложение на телефоне моего друга, но он тоже рухнул, так как никогда раньше не падал ни на одном из них. Совпадение?
Любая помощь с благодарностью. Спасибо!