Пожалуйста, не стесняйтесь пропустить вопрос, так как это понимание фона может не понадобиться для вас.Невозможно удалить страницы при использовании FragmentStatePagerAdapter. Каково обычное поведение идентификаторов строк при использовании целочисленного первичного ключа?
Я новичок в android и sqlite, и я разрабатываю приложение, у которого есть поставщик контента для доступа к базе данных sqlite с несколькими таблицами. Существует несколько действий, которые используют разные адаптеры для отображения информации из базы данных в пользовательский интерфейс (например, адаптеры курсора, адаптер страницы состояния фрагмента и адаптеры массивов). У меня возникли проблемы с функцией удаления во всех моих действиях, которые не используют адаптер курсора. Когда я пытаюсь обновить или удалить строку из таблицы, она удалит неправильную строку или вообще ничего не удалит. Я считаю, что это проблема с адаптером, где я пытаюсь выяснить, какая строка предназначена для отправки правильной информации поставщику контента.
Идентичный код Java отлично работает с адаптером курсора, а строки удаляются нормально, а другие операции CRUD работают. Функции вставки и запроса работают нормально для всех таблиц. Код провайдера использует оператор switch для каждой таблицы, но он в основном идентичен для каждого случая Uri. Все таблицы имеют _id как целочисленный первичный ключ, который НЕ установлен для автоматического увеличения. Поскольку я не совсем понимаю, как работает идентификатор строки, мой код Java не отражает его, и у меня все эти проблемы. Хотя я прочитал много документов о контент-провайдерах, адаптерах, базах данных sqlite и т. Д., Некоторые ключевые данные мне не понятны.
Мой вопрос: Как идентификатор строки получает присвоенные номера в базе данных, когда в качестве первичного ключа установлен столбец _id, и что происходит с этими числами при изменении базы данных?
Например, у меня есть пустая база данных. Изначально после вставки первой строки Uri вернет сегмент пути для строки 0, а позиция адаптера будет равна 0 ..., каков будет идентификатор строки для базы данных (0 или 1)?
Затем для каждой строки, которую я вставляю, я знаю, что число строк увеличится на одно целое число. Скажем, я вставляю 4 строки - 0,1,2,3. Теперь, когда я готов удалить - должен ли последний сегмент пути на Uri быть одним целым числом меньше числа строк (например, я отправляю Uri с последним сегментом пути 2 для удаления строки 3)? Наконец, после удаления, идентификаторы строк затем автоматически будут переназначены так, что строка 4 теперь станет третьей строкой? Есть ли какой-то код, который мне нужно написать, чтобы это произошло в базе данных? Первичные ключи не настроены на автоматическое увеличение.
У меня есть разные адаптеры и действия, где я не могу получить доступ к фактическому идентификатору строки базы данных после отображения данных в пользовательском интерфейсе, поэтому я использую позицию адаптера в качестве суррогата. Вот почему у меня возникают проблемы с обновлением и удалением. Большое спасибо, если вы прочитали весь этот вопрос и нашли время ответить на него, это очень помогло бы мне.
У меня есть активность, которая имеет вкладку и использует FragmentStatePagerAdapter, который заполняется базой данных. Вот адаптер, который я настроил, чтобы следить за строками:
**EDITED:**
public class TankSectionsPagerAdapter extends FragmentStatePagerAdapter {
private ArrayList<Fragment> tankFragments = new ArrayList<>();
private ArrayList<String> tankTitles = new ArrayList<>();
//I added this ArrayList below to store the tankIDs to match the Fragments//
**public ArrayList<Integer> tankIDs = new ArrayList<>();**
public TankSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return tankFragments.get(position);
}
@Override
public int getCount() {
return tankFragments.size();
}
@Override
public String getPageTitle(int position) {
return tankTitles.get(position);
}
public void addPage(Fragment fragment, String tankName) {
tankFragments.add(fragment);
tankTitles.add(tankName);
// I added this below so the ID position would match each fragment position //
**tankIDs.add(tankId);**
notifyDataSetChanged();
}
// Finally I added this method below to the adapter//
** public ArrayList<Integer> getPageId(){
return tankIDs;
}**
Вот активность, где вызывается метод и где он вытаскивает данные из курсора для перехода к адаптеру. Существует цикл, где каждая строка создает (вкладка) страницы в ViewPager:
public class MyClass extends Tank implements TabLayout.OnTabSelectedListener, LoaderManager.LoaderCallbacks<Cursor> {
public TankSectionsPagerAdapter tankSectionsPagerAdapter;
TabLayout tabLayout;
private ViewPager mViewPager;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_class);
mViewPager = (ViewPager) findViewById(R.id.container);
addPages(mViewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.addOnTabSelectedListener(this);
}
public void addPages(ViewPager mViewPager) {
tankSectionsPagerAdapter = new TankSectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(tankSectionsPagerAdapter)
try {
...
Cursor cursor = getContentResolver().query(MyProvider.CONTENT_URI_TABLE_TANK_SETUP, MyDatabaseHelper.ALL_TABLE_TANK_SETUP_COLUMNS, tankDataFilter, null, null);
if (cursor.moveToFirst()) {
do {
tName = cursor.getString(cursor.getColumnIndex(MyDatabaseHelper.TANK_NAME)); ...
// all the variables are stored in the bundle passed to the fragment/
...
**tankSectionsPagerAdapter.addPage(MainTankFragment.newInstance(tankBundle),tName, int tankID);**
tankDataFilter = tankDataFilter + (-1);
}
while (cursor.moveToNext());
cursor.close();
} else {
Toast...
}
} catch (Exception e) {
Toast..
}
}
...
// Get Row ID from cursor(tankID), parameter in addPage() above//
//Get ID's from Adapter //
** ArrayList <Integer> pageID= tankSectionsPagerAdapter.getPageId();**
Это активность с Spinner, чтобы выбрать строки/фрагменты для редактирования или удаления.
public class EditTank extends Tank implements LoaderManager.LoaderCallbacks<Cursor>
...
// Get the ArrayList//
ArrayList<Integer> IDtags =getIDIntent.getIntegerArrayListExtra("tank_edit_key");
loadEditTankSpinnerData();
////***Here is the Spinner. Use row ID from the ArrayList******
Note: Don't use the id of the spinner
editTankSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view int position, long id) {
*** tankID = IDtags.get(position); ***
}
private void loadEditTankSpinnerData() {
List<String> tankNames = new ArrayList<String>();
Cursor cursor = getContentResolver().query(MyProvider.CONTENT_URI_TABLE_TANK_SETUP, MyDatabaseHelper.TANK_NAMES, null, null,null);
try{
if (cursor.moveToFirst()) {
do {
tankNames.add(cursor.getString(1));
} while (cursor.moveToNext());
cursor.close();
} else {
deleteTankBtn.setEnabled(false);
editTankBtn.setEnabled(false);
Toast...
}
} catch (Exception e) {
Toast...
}
...
}
Приведенный выше код работает хорошо с CursorAdapter, но не с fragmentStatePagerAdapter (*** До правок он не работал, теперь он работает хорошо и удаляет правильно).
Я потратил дни (недели) на это, потому что я не понимал, почему строки не удаляются. Я надеюсь, что это помогает кому-то.
Вы видели последний параметр метода OnItemClickListener # onItemClick? – pskink
Да, я понимаю, что вы имеете в виду, последний параметр - id. Однако у меня есть некоторые действия, которые не используют onItemClick напрямую. Например, у меня есть активность с вкладками, которая использует адаптер пейджера состояния фрагмента для добавления фрагментов на основе цикла вытягивания курсора из базы данных. Я использую счетчик, чтобы указать, какой фрагмент выбирается на основе имени вкладки (я не понял, как получить идентификатор из вкладки непосредственно наTabSelected). Однако, когда элемент выбран и идентификатор извлекается из счетчика, он не приводит к удалению правильной строки в базе данных. – GreenTea
Когда столбец «INTEGER PRIMARY KEY», он всегда автоинкремент. И вы не должны использовать позицию в списке, это не будет работать с фильтрованным/отсортированным списком. –