請隨意跳到了一個問題,這樣的背景下理解可能沒有必要爲您服務。使用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」時,它總是自動增量。而且你不能使用列表中的位置,這對於過濾/排序列表不起作用。 –