Я пытался придерживаться startManagingCursor() для своей базы данных SQLite, доступной только для чтения, но он выдает много ошибок, даже если я использую stopManagingCursor() (да, я знаю они устарели).
Я хотел бы получить некоторую помощь, чтобы узнать, как перейти от управления курсорами к лучшему методу без особых изменений, так как я никогда их не использовал, и этот код в какой-то мере стабилен, хотя случайные ошибки время от времени появляются из-за startManagingCursor() ( в приложении с одним действием он работает нормально, но при использовании его в качестве фрагмента в мультифрагментном приложении это становится действительно проблематичным).
Однако, когда я просто меняю startManagingCursor() на getLoaderManager(), он по-прежнему работает, но в документации также говорится, что он устарел указывает на getSupportLoaderManager(), а когда я использую этот, он вычеркивается, как будто он также устарел (Линт говорит, что «getSupportLoaderManager() устарел», но не говорит, что то же для getLoaderManager()); и они могут производить java.lang.NullPointerException, чего не происходило с startManagingCursor(cursor), хотя оба они работоспособны.
Так что же мне тогда делать?
Фрагмент SQLite таков:
public class SQLiteDatabaseActivity extends Fragment {
public static SQLiteDatabaseActivity newInstance() {
return new SQLiteDatabaseActivity();
}
ExpandableListView expandableListView;
Database mDatabase;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.sqlite_database_activity, container, false);
mDatabase = new Database(getActivity());
mDatabase.open();
Cursor cursor = mDatabase.getDatabase();
getActivity().startManagingCursor(cursor);
String[] groupFrom = {
Database.DATABASE_GROUP_1,
Database.DATABASE_GROUP_2,
Database.DATABASE_GROUP_3,
Database.DATABASE_GROUP_4
};
int[] groupTo = {
R.id.group_number,
R.id.group_name,
R.id.group_path,
R.id.group_company
};
String[] childFrom = new String[]{
Database.DATABASE_CHILD_1,
Database.DATABASE_CHILD_2,
Database.DATABASE_CHILD_3,
Database.DATABASE_CHILD_4,
Database.DATABASE_CHILD_5,
Database.DATABASE_CHILD_6,
Database.DATABASE_CHILD_7,
Database.DATABASE_CHILD_8,
Database.DATABASE_CHILD_9,
Database.DATABASE_CHILD_10,
Database.DATABASE_CHILD_11,
Database.DATABASE_CHILD_12
};
int[] childTo = {
R.id.child1,
R.id.child2,
R.id.child_saturday_origin,
R.id.child_saturday_destiny,
R.id.child_sunday_origin,
R.id.child_sunday_destiny,
R.id.child_origin,
R.id.child_destiny,
R.id.child_saturday_origin_origin,
R.id.child_saturday_destiny_destiny,
R.id.child_sunday_origin_origin,
R.id.child_sunday_destiny_destiny
};
SimpleCursorTreeAdapter simplecursortreeAdapter = new ExpandableListViewAdapter(
getActivity(),
cursor,
R.layout.sqlite_database_list_group,
groupFrom,
groupTo,
R.layout.sqlite_database_list_child,
childFrom,
childTo
);
expandableListView = view.findViewById(R.id.expandableListview);
expandableListView.setAdapter(simplecursortreeAdapter);
getActivity().stopManagingCursor(cursor);
return view;
}
private class ExpandableListViewAdapter extends SimpleCursorTreeAdapter {
private ExpandableListViewAdapter(
Context context,
Cursor cursor,
int groupLayout,
String[] groupFrom,
int[] groupTo,
int childLayout,
String[] childFrom,
int[] childTo) {
super(context, cursor, groupLayout, groupFrom, groupTo, childLayout, childFrom, childTo);
}
protected Cursor getChildrenCursor(Cursor groupCursor) {
return mDatabase.getID(groupCursor.getInt(groupCursor.getColumnIndex(Database.DATABASE_ID)));
}
}
public void onDestroy() {
super.onDestroy();
mDatabase.close();
}
}
База данных находится здесь:
public class Database {
private static final int DATABASE_VERSION = 3;
private static final String DATABASE_NAME = "BusScheduleDatabase.db";
private static final String DATABASE_TABLE = "BusSchedule";
public static final String DATABASE_ID = "_id";
public static final String DATABASE_GROUP_1 = "Linha";
public static final String DATABASE_GROUP_2 = "Nome";
public static final String DATABASE_GROUP_3 = "Caminho";
public static final String DATABASE_GROUP_4 = "Empresa";
public static final String DATABASE_CHILD_1 = "SemanaIda";
public static final String DATABASE_CHILD_2 = "SemanaVolta";
public static final String DATABASE_CHILD_3 = "SabadoIda";
public static final String DATABASE_CHILD_4 = "SabadoVolta";
public static final String DATABASE_CHILD_5 = "DomingoIda";
public static final String DATABASE_CHILD_6 = "DomingoVolta";
public static final String DATABASE_CHILD_7 = "Origem";
public static final String DATABASE_CHILD_8 = "Destino";
public static final String DATABASE_CHILD_9 = "Origem";
public static final String DATABASE_CHILD_10 = "Destino";
public static final String DATABASE_CHILD_11 = "Origem";
public static final String DATABASE_CHILD_12 = "Destino";
private final Context mContext;
private DatabaseHelper mDatabaseHelper;
private SQLiteDatabase mDB;
public Database(Context context) {
mContext = context;
}
public void open() {
mDatabaseHelper = new DatabaseHelper(mContext, DATABASE_NAME, null, DATABASE_VERSION);
mDB = mDatabaseHelper.getReadableDatabase();
}
public void close() {
if (mDatabaseHelper != null) mDatabaseHelper.close();
}
public Cursor getDatabase() {
return mDB.query(DATABASE_TABLE, null, null, null, null, null, DATABASE_GROUP_1);
}
public Cursor getID(long rowID) {
return mDB.query(DATABASE_TABLE, null, "_id" + " = "
+ rowID, null, null, null, null);
}
public class DatabaseHelper extends SQLiteAssetHelper {
public DatabaseHelper(Context mContext, String DATABASE_NAME, SQLiteDatabase.CursorFactory factory, int DATABASE_VERSION) {
super(mContext, DATABASE_NAME, factory, DATABASE_VERSION);
super.setForcedUpgrade();
}
}
}
И повторяющаяся ошибка в основном заключается в следующем:
java.lang.IllegalStateException: this should only be called when the cursor is valid
Заранее большое спасибо за помощь!
@MikeM., Я могу еще раз поблагодарить вас! Ваши слова всегда служат хорошим ориентиром, и я изучу то, что вы здесь принесли. Я все еще не знаком с AndroidX, но посмотрю, что с этим можно сделать. Еще раз спасибо!
Совершенно никаких проблем. Однако я действительно должен упомянуть, что ViewModel / LiveData / Observer - это текущая «блестящая новинка» в Android, и многие рекомендуют вам реализовать все это самостоятельно. (Общий обзор и руководство для этого здесь.) Однако для относительно простых проектов и тех, которые могут не нуждаться в большом количестве тестирования, это может быть огромным излишеством. IMO, Loader великолепны, потому что они могут управлять, поэтому, если ваш проект работает с ними так, как вам нравится, я не вижу проблем в том, чтобы придерживаться их. Ваше здоровье!
Я согласен, и я прочитал много предложений об этом новом способе решения этой проблемы, но я не так хорошо разбираюсь в этом, поэтому нелегко перейти с одного места на другое без особого изучения, усилий и времени. Я хотел бы придерживаться его, потому что это список расписаний, доступный только для чтения, с 25 группами по 8 элементов в каждой. Базу данных было достаточно сложно собрать, и теперь я просто хочу, чтобы она не ломалась. Изменение startManagingCursor и закрытие onPause сделали его действительно лучше, но для этого нужно больше тестов (многие открытые группы кажутся проблемой). AndroidX может помочь использовать метод, который не является устаревшим и не вызывает исключения.




Если вы хотите придерживаться структуры
Loader, я думаю, что самая новая версия в библиотеках androidx не должна быть устаревшей, поскольку они переписали ее, чтобы она была оболочкой для новых компонентов архитектурыViewModel/Observer. Если вы еще не знакомы с androidx, это просто следующая версия библиотек поддержки, но с некоторым рефакторингом пакетов и другими общими улучшениями. На эта страница разработчика есть обзор и соответствующие ссылки.