[英]Android SQLite - Joining two tables and render the result as list
我在sqlite中有兩個表:
projects
---id
---projectname
outlets
---id
---pid
---outletname
---status
我要渲染的projectname
和outletname
其中status
滿足條件。 我想將結果輸出呈現為列表。 我正在使用以下代碼:
private void showProjectStatus() {
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
cursor = sqLiteDatabase.rawQuery("select projectName, OutletName from projects inner join outlets on outlets.pid = projects.id where outlets.Status = 1"+"", null);
//cursor = sqLiteDatabase.rawQuery("SELECT * FROM '"+SQLiteHelper.TABLE_NAME1+"' where Status = 1"+"", null);
上面的光標完美地工作。
ID_Array.clear();
ProjectName_Array.clear();
OutletName_Array.clear();
if (cursor != null && cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
ID_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_ID)));
OutletName_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_PID)));
ProjectName_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_OutletName)));
我需要幫助來渲染上述內容。 如何將游標返回的值直接呈現為列表,而不是引用表中的實際列。
} while (cursor.moveToNext());
}
} else {
Toast.makeText( this, "No data to display!", Toast.LENGTH_SHORT ).show();
}
我需要幫助來渲染上述內容。 如何將游標返回的值直接呈現為列表,而不是引用表中的實際列。
簡而言之,您不能使用標准 API(並且使用替代方法而不是 Cursor 似乎不會更困難,您將獲得結果集)。 所以一個 Cursor 就是你從中得到的結果。
查看您的代碼,當您試圖從 Cursor 獲取不存在的值時,您可能會感到困惑。
通過使用SELECT projectName, OutletName FROM .....
你會得到一個 Cursor 像(2 列):-
你是說你想要在 Cursor 中有兩列,他們的名字是projectName和OutletName 。 嘗試使用cursor.getColumnIndex(SQLiteHelper.Table1_Column_ID)
將導致返回 -1(在 Cursor 中找不到列名)並且 Cursor 中沒有偏移量為 -1 的列。
PID 也是如此。
如果除了 outletName 和 projectName 列之外還需要 ID 和 PID 列,則將查詢更改為:-
cursor = sqLiteDatabase.rawQuery("select projects.id,pid,projectName, OutletName from projects inner join outlets on outlets.pid = projects.id where outlets.Status = 1"+"", null).
在這種情況下,光標將類似於(4 列):-
假設您想要所有四列,請在單獨的數組中進行檢查,然后可能會考慮:-
private void showProjectStatus() {
ID_Array.clear();
ProjectName_Array.clear();
OutletName_Array.clear();
sqLiteDatabase = sqLiteHelper.getWritableDatabase();
Cursor cursor = sqliteDatabase.query(
"projects inner join outlets on outlets.pid = projects.id",
new String[]{
"projects." + SQLiteHelper.Table1_Column_ID,
SQLiteHelper.Table1_Column_PID,
"projectName", //<<<<< defined value not used as unknown
SQLiteHelper.Table1_Column_OutletName
},
"outlets.Status=1",
null,null,null,null
);
while (cursor.moveToNext()) {
ID_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_ID));
ProjectName_Array.add(cursor.getString(cursor.getColumnIndex("projectName"));
OutletName_Array.add(cursor.getString(cursor.getColumnIndex(SQLiteHelper.Table1_Column_OutletName));
}
cursor.close()
}
注意以上代碼為原則性代碼; 它尚未運行或測試,因此可能包含一些錯誤。
但是,當您似乎想要驅動ListView 時,如果您使用CursorAdapter的子類,則適配器可以代表您完成大部分工作。
SimpleCursorAdapter ,這樣的適配器,非常靈活,允許布局顯示多列。 CursorAdapters 的顯着優點之一是 ItemSelection (Click LongClick) 事件將id傳遞給方法(對於非 CursorAdapters,傳遞的值是作為 long 的位置)。 要做到這一點,游標必須有一個特別名為_id的列( Base.Columns._ID
),並且該列應該是 rowid 的別名(即表中的列是使用INTEGER PRIMARY KEY
(可選地使用 AUTOINCREMENT)定義的)。
public class SQLiteHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb";
public static final int DBVERSION = 1;
public static final String TABLE_NAME1 = "projects";
public static final String TABLE_NAME2 = "outlets";
public static final String TABLE1_COLUMN_ID = BaseColumns._ID;
public static final String TABLE1_COLUMN_PROJECTNAME = "projectname";
public static final String TABLE2_COLUMN_ID = BaseColumns._ID;
public static final String TABLE2_COLUMN_PID = "pid";
public static final String TABLE2_COLUMN_OUTLETNAME = "outletname";
public static final String TABLE2_COLUMN_STATUS = "status";
public SQLiteHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
@Override
public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
}
@Override
public void onCreate(SQLiteDatabase db) {
String createProjectsTableSQL =
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME1 +
"(" +
TABLE1_COLUMN_ID + " INTEGER PRIMARY KEY," +
TABLE1_COLUMN_PROJECTNAME + " TEXT" +
")";
String createOutletsTableSQL =
"CREATE TABLE IF NOT EXISTS " + TABLE_NAME2 +
"(" +
TABLE2_COLUMN_ID + " INTEGER PRIMARY KEY," +
TABLE2_COLUMN_PID + " INTEGER REFERENCES " + TABLE_NAME1 + "(" +
TABLE1_COLUMN_ID +
") ON DELETE CASCADE ON UPDATE CASCADE, " +
TABLE2_COLUMN_OUTLETNAME + " TEXT," +
TABLE2_COLUMN_STATUS + " INTEGER" +
")";
db.execSQL(createProjectsTableSQL);
db.execSQL(createOutletsTableSQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
public long addProject(String projectName) {
ContentValues cv = new ContentValues();
cv.put(TABLE1_COLUMN_PROJECTNAME,projectName);
return this.getWritableDatabase().insert(TABLE_NAME1,null,cv);
}
public long addOutlet(String outletName, long projectId, boolean status) {
ContentValues cv = new ContentValues();
cv.put(TABLE2_COLUMN_OUTLETNAME,outletName);
cv.put(TABLE2_COLUMN_PID,projectId);
cv.put(TABLE2_COLUMN_STATUS,status);
return this.getWritableDatabase().insert(TABLE_NAME2,null,cv);
}
public Cursor getProjectsWithOutletsWithStatusOn() {
return this.getWritableDatabase().query(
TABLE_NAME1 + " INNER JOIN "
+ TABLE_NAME2 + " ON " +
TABLE_NAME1 + "." + TABLE1_COLUMN_ID + "=" +
TABLE_NAME2 + "." + TABLE2_COLUMN_PID,
new String[]{
TABLE_NAME1 + "." + TABLE1_COLUMN_ID,
TABLE2_COLUMN_PID,
TABLE1_COLUMN_PROJECTNAME,
TABLE2_COLUMN_OUTLETNAME,
TABLE2_COLUMN_STATUS //? optional as will always be 1
},
TABLE2_COLUMN_STATUS + "=1",
null,null,null,null
);
}
}
public class MainActivity extends AppCompatActivity {
SQLiteHelper mHelper;
Cursor mCursor;
SimpleCursorAdapter mAdapter;
ListView mListView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListView = this.findViewById(R.id.listview);
mHelper = new SQLiteHelper(this);
addSomeDataIfNone();
manageListView();
}
@Override
protected void onDestroy() {
super.onDestroy();
mCursor.close(); // close the Cursor (more important for invoked activities)
}
@Override
protected void onResume() {
super.onResume();
manageListView(); // refresh Listview when resuming activity as data may have changed
}
private void addSomeDataIfNone() {
if (DatabaseUtils.queryNumEntries(mHelper.getWritableDatabase(),SQLiteHelper.TABLE_NAME1) < 1) {
long idp1 = mHelper.addProject("Project001");
mHelper.addOutlet("OutletP1001",idp1,false);
mHelper.addOutlet("OutletP1002",idp1,true);
mHelper.addOutlet("Outletp1003",idp1,true);
long idp2 = mHelper.addProject("Prject002");
mHelper.addOutlet("OutletP2001",idp2,true);
mHelper.addOutlet("OutletP2002",idp2,false);
}
}
private void manageListView() {
mCursor = mHelper.getProjectsWithOutletsWithStatusOn();
if (mAdapter == null) {
mAdapter = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_2,
mCursor,
new String[]{
SQLiteHelper.TABLE1_COLUMN_PROJECTNAME,
SQLiteHelper.TABLE2_COLUMN_OUTLETNAME
},
new int[]{
android.R.id.text1,
android.R.id.text2
},
0
);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(view.getContext(),
"You clicked " +
"Project = " + mCursor.getString(mCursor.getColumnIndex(SQLiteHelper.TABLE1_COLUMN_PROJECTNAME)) +
" Outlet = " + mCursor.getString(mCursor.getColumnIndex(SQLiteHelper.TABLE2_COLUMN_OUTLETNAME)) +
" Project ID = " + mCursor.getString(mCursor.getColumnIndex(SQLiteHelper.TABLE1_COLUMN_ID)) +
" Outlet Status = " + (mCursor.getInt(mCursor.getColumnIndex(SQLiteHelper.TABLE2_COLUMN_STATUS))> 0)
,
Toast.LENGTH_SHORT).show();
}
});
} else {
mAdapter.swapCursor(mCursor);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.