我是Android Studio的新手,
我已经有3列(ID,标题,详细信息)的数据库文件
我想从数据库中创建一个包含“标题”的ListView,当我单击其中一个标题时,它将转到下一个活动并显示我之前单击的标题的“详细信息”。
数据库文件位于资产文件夹中。
我正在使用最新版本的Android Studio,请帮助我xml,java和清单代码。谢谢。
这是我的代码,我只能成功在ListView中显示“ title”列,而其余部分我一无所知。
public class MainActivity extends AppCompatActivity {
static final String DBNAME = "story.db";
static final String DBASSETPATH = "databases/" + DBNAME;
static final String DBTABLE = "table";
static final String DBTITLE = "title";
static final String IDCOLUMN = "_id";
ListView mTableList;
SQLiteDatabase mDB;
SimpleCursorAdapter mSCA;
Cursor mCsr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTableList = (ListView) this.findViewById(R.id.storylist);
mDB = openStoryDB();
if (mDB != null) {
mCsr = mDB.query(DBTABLE,
new String[]{IDCOLUMN + " AS _id",
DBTITLE
},
null,null,null,null,null);
mSCA = new SimpleCursorAdapter(this,android.R.layout.simple_list_item_1,mCsr,
new String[]{DBTITLE},
new int[]{android.R.id.text1},0);
mTableList.setAdapter(mSCA);
} else {
Toast.makeText(this,"Unable to open Database.",Toast.LENGTH_LONG);
}
}
private SQLiteDatabase openStoryDB() {
String dbpath = this.getDatabasePath(DBNAME).getPath();
if (this.getDatabasePath(DBNAME).exists()) {
Log.d("OPENSTORYDB","Opening already existing Database");
return SQLiteDatabase.openDatabase(dbpath,null,SQLiteDatabase.OPEN_READWRITE);
}
InputStream is;
byte[] buffer;
FileOutputStream db;
try {
is = this.getAssets().open(DBASSETPATH);
buffer = new byte[is.available()];
is.read(buffer);
is.close();
} catch (Exception e) {
e.printStackTrace();
Log.d("OPENSTORYDB","Unable to locate or buffer input from assets " + DBASSETPATH);
return null;
}
// Just in case the databases directory doesn't exist create it.
File dbmkdir = (this.getDatabasePath(DBNAME)).getParentFile();
dbmkdir.mkdirs();
try {
db = new FileOutputStream(this.getDatabasePath(DBNAME).getPath());
} catch (Exception e) {
e.printStackTrace();
Log.d("OPENSTORYDB","Unable to create outputstream for DB at path " + dbpath);
try {
is.close();
} catch (Exception e2) {
}
return null;
}
try {
db.write(buffer);
db.flush();
db.close();
is.close();
} catch (Exception e) {
Log.d("OPENSTORYDB","Failed to copy asset to DB");
e.printStackTrace();
return null;
}
return SQLiteDatabase.openDatabase(dbpath,null,SQLiteDatabase.OPEN_READWRITE);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.book.story.MainActivity">
<ListView
android:id="@+id/storylist"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>
答案 0 :(得分:2)
您需要
以下是基于您的问题的示例。
名为 mydb 的数据库,也就是资产文件夹中名为 mydb 的文件,其表 mytable 包含以下内容:->
一个简单的布局,包括一个名为ID的Listview,已用于名为 MainActivity 的活动,该ListView的代码为:-
<ListView
android:id="@+id/myListView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
数据库帮助器已创建为 DBHelper.java 。实例化时,它将检查数据库是否以文件形式存在,如果不存在,则尝试从资产文件夹中复制数据库(如果失败,则抛出运行时异常,例如,如果资产不存在)。然后打开数据库。有一个公共方法 getAllFromMytable 返回一个带有mytable表中所有行的Cursor:-
public class DBHelper extends SQLiteOpenHelper {
public static final String DBNAME = "mydb"; //<<<<<<<<<< Database file name including extension
public static final int DBVERSION = 101;
public static final String TBL_MYTABLE = "mytable"; //<<<<<<<<<< The table name
public static final String COL_MYTABLE_ID = "id"; //<<<<<<<<<< The id column name
public static final String COl_MYTABLE_TITLE = "title"; //<<<<<<<<<< The title column name
public static final String COL_MYTABLE_DETAILS = "details"; //<<<<<<<<<< The details column name
Context mContext;
SQLiteDatabase mDB;
public DBHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
mContext = context;
if(!ifDBExists()) {
copyDatabaseFromAssetsFolder();
}
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
super.onDowngrade(db, oldVersion, newVersion);
}
public Cursor getAllFromMytable() {
String[] columns = new String[]{"*, id AS " + BaseColumns._ID}; //<<<<<<<<<< need column named _id so generate it
return mDB.query(TBL_MYTABLE,columns,null,null,null,null,null);
}
private void copyDatabaseFromAssetsFolder() {
int stage = 0, buffer_size = 4096, blocks_copied = 0, bytes_copied = 0;
try {
InputStream is = mContext.getAssets().open(DBNAME);
stage++;
OutputStream os = new FileOutputStream(mContext.getDatabasePath(DBNAME));
stage++;
byte[] buffer = new byte[buffer_size];
int length;
while ((length = is.read(buffer))>0) {
blocks_copied++;
os.write(buffer, 0, length);
bytes_copied += length;
}
os.flush();
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
String exception = "";
switch (stage) {
case 0:
exception = "Unable to open asset file " + DBNAME;
break;
case 1:
exception = "Unable to open the Database file " + DBNAME + " for output.";
break;
case 2:
exception = "Error whilst copying " + DBNAME +
" from the assets folder to " + mContext.getDatabasePath(DBNAME).toString() +
" - successfully copied " + String.valueOf(blocks_copied) + " blocks."
;
}
throw new RuntimeException(exception + " (see stack-trace above)");
}
}
// Check if the Database exists
private boolean ifDBExists() {
File db = mContext.getDatabasePath(DBNAME);
if (db.exists()) return true;
if (!db.getParentFile().exists()) {
db.getParentFile().mkdirs();
}
return false;
}
}
这执行4-7,除了不是通过启动另一个活动,而是通过Toast显示ListView中被单击项的详细信息:-
public class MainActivity extends AppCompatActivity {
ListView mMyListView;
DBHelper mDBHlpr;
Cursor mCsr;
SimpleCursorAdapter mSCA;
Context mContext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
mDBHlpr = new DBHelper(this); //<<<<<<<<<< Instantiate the DBHelper
mMyListView = this.findViewById(R.id.myListView);
}
private void manageListView() {
mCsr = mDBHlpr.getAllFromMytable(); //<<<<<<<<<< get the latest data from the database
if (mSCA == null) {
mSCA = new SimpleCursorAdapter(
this,
android.R.layout.simple_list_item_1,mCsr,
new String[]{DBHelper.COl_MYTABLE_TITLE},
new int[]{android.R.id.text1},
0
);
mMyListView.setAdapter(mSCA);
mMyListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Start the other activity here passing the id (sufficient to find the specififc row)via an intent extra
// Toast used as an example of extracting the respective data from the cursor
Toast.makeText(
mContext,
"You clicked on the row with an id of " + String.valueOf(id) +
" the Title is " + mCsr.getString(mCsr.getColumnIndex(DBHelper.COl_MYTABLE_TITLE)) +
" the Details are " + mCsr.getString(mCsr.getColumnIndex(DBHelper.COL_MYTABLE_DETAILS)) +
" the id column is " + String.valueOf(mCsr.getLong(mCsr.getColumnIndex(DBHelper.COL_MYTABLE_ID))),
Toast.LENGTH_SHORT
).show();
}
});
} else {
mSCA.swapCursor(mCsr);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mCsr.close(); //<<<<<<<<<< ensure that the cursor is closed when done with
}
@Override
protected void onResume() {
super.onResume();
manageListView(); //<<<<<<<<<< refresh the listview
}
}
Toast的屏幕截图:-
将ID传递给另一个活动,然后提取该活动中的详细信息列。
首先,向数据库帮助器类中添加一个新方法,以允许详细信息列作为字符串返回并根据 id
获得例如上面的DBHelper.java将添加以下内容:-
public String getDetailsFromId(long id) {
String rv = "";
String whereclause = COL_MYTABLE_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
Cursor csr = mDB.query(TBL_MYTABLE,null,whereclause,whereargs,null,null,null);
if (csr.moveToFirst()) {
rv = csr.getString(csr.getColumnIndex(COL_MYTABLE_DETAILS));
}
csr.close();
return rv;
}
创建另一个活动以确保在清单中定义了该活动(使用File / New / Activity相应地修改了清单)。
此活动可能是类似的(它将显示ID的详细信息,该ID通过用于启动活动的意图附加信息传递的时间很长):-
public class OtherActivity extends AppCompatActivity {
public static final String INTENTKEY_MYTABLEIDCOLUMNS = "ikey_mytableidcolumn";
TextView mDetails;
DBHelper mDBHlpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
mDetails = this.findViewById(R.id.mydetails);
mDBHlpr = new DBHelper(this);
long id = this.getIntent().getLongExtra(INTENTKEY_MYTABLEIDCOLUMNS,-1);
mDetails.setText(mDBHlpr.getDetailsFromId(id));
}
}
最后修改初始活动,以实例化可用于启动其他活动的Intent,然后将id用作额外内容,最后启动其他活动,例如在上面的活动中,可以使用以下内容代替(以及(如果需要))Toast:-
mMyListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Start the other activity here passing the id (sufficient to find the specififc row)via an intent extra
// Toast used as an example of extracting the respective data from the cursor
/*
Toast.makeText(
mContext,
"You clicked on the row with an id of " + String.valueOf(id) +
" the Title is " + mCsr.getString(mCsr.getColumnIndex(DBHelper.COl_MYTABLE_TITLE)) +
" the Details are " + mCsr.getString(mCsr.getColumnIndex(DBHelper.COL_MYTABLE_DETAILS)) +
" the id column is " + String.valueOf(mCsr.getLong(mCsr.getColumnIndex(DBHelper.COL_MYTABLE_ID))),
Toast.LENGTH_SHORT
).show();
*/
Intent i = new Intent(mContext,OtherActivity.class);
i.putExtra(OtherActivity.INTENTKEY_MYTABLEIDCOLUMNS,id);
startActivity(i);
}
});
结果(根据单击项目时的其他活动(在这种情况下为第一个)):-