请随意跳到了一个问题,这样的背景下理解可能没有必要为您服务。使用FragmentStatePagerAdapter时无法删除页面 - 使用整数主键时,行ID的常见行为是什么?
我是新来的android和sqlite,我正在设计一个应用程序,它有一个内容提供者访问一个sqlite数据库与多个表。有几种活动使用不同的适配器来显示从数据库到UI的信息(即游标适配器,分段状态页面适配器和阵列适配器)。我一直在使用不使用游标适配器的所有活动中的删除功能问题。当我尝试从表中更新或删除一行时,它会删除错误的行,或者根本不删除任何内容。我相信这是适配器的问题,我试图找出将哪个行发送给内容提供商的正确信息。
相同的Java代码工作完全用光标适配器和行正常删除和其他CRUD操作工作。插入和查询函数对所有表都正常工作。提供程序代码为每个表使用switch语句,但对于每个Uri情况,它基本相同。所有表都有_id作为未设置为自动增量的整数主键。由于我不完全理解行号是如何工作的,所以我的java代码没有反映出来,而且我一直都有这些问题。尽管我已经阅读了许多关于内容提供者,适配器,sqlite数据库等的文档,但某些关键细节并不清楚。
我的问题是当数据库设置为_id列作为主键时,行ID如何获取数据库中的分配号码,以及数据库更改时会发生什么?
例如,说我有一个空数据库。最初插入第一行后,Uri将返回0行的路径段,并且适配器位置将为0 ...数据库的行ID为(0或1)是什么?
然后为每一行我插入,我知道,行号会被一个整数增加。说我插入4行 - 0,1,2,3。现在,当我准备删除 - 应该对URI的最后一个路径段是一个整数比的行数(即我送一个URI为2的最后路径段删除第3行)少了?最后,在删除之后,行ID会自动重新分配,以便第4行现在变成第3行?是否有一些代码需要编写才能在数据库中实现?主键未设置为自动增量。
我有不同的适配器和活动的地方一旦数据被显示在UI我无法访问实际的数据库行ID,所以我使用的适配器位置作为替代。这就是为什么我在更新和删除时遇到问题。 非常感谢您阅读完整个问题并花时间回答问题,这对我非常有帮助。
我有一个选项卡式的活动,并使用由数据库填充的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();**
这是微调活动来选择行/片段进行编辑或删除。
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。例如,我有一个选项卡式活动,它使用片段状态寻呼机适配器根据从数据库拉出的光标循环添加片段。我使用微调来指示选择哪个片段基于选项卡名称(我还没有想过如何直接从onTabSelected获得标签中的id)。但是,当选择该项目并从微调器中检索标识时,它不会导致删除数据库中的正确行。 – GreenTea
当该列是“INTEGER PRIMARY KEY”时,它总是自动增量。而且你不能使用列表中的位置,这对于过滤/排序列表不起作用。 –