如何将房间数据库连接到自定义 ListView
How to connect Room Database to Custom ListView
我正在 android 上使用 Room Database 创建一个密码管理器。我想使用自定义 ListView,但找不到任何方法将我的房间数据库连接到自定义列表视图布局。我想我应该为我的列表视图制作一个适配器,但我不知道如何制作。寻找它,但无法做到。我该怎么做?
我通过以下方式获取数据库列表:
AppDatabase db = AppDatabase.getDbInstance(this.getApplicationContext());
List<Password> passwordList = db.passwordDAO().getAllPasswords();
我的道:
@Dao
public interface PasswordDAO {
@Query("SELECT * FROM password")
List<Password> getAllPasswords();
@Query("SELECT hashed_password FROM password")
ArrayList<Password> getAllHashedPasswords();
@Query("SELECT app_name FROM password")
ArrayList<Password> getAllAppNames();
@Query("SELECT uid FROM password")
ArrayList<Password> getAllIDs();
@Insert
void insertUser(Password... passwords);
@Delete
void delete(Password password);
我的自定义 ListView 布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/_80sdp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="App Name"
android:id="@+id/customListView_AppName"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/_10sdp"
android:textSize="@dimen/_20sdp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/customListView_HashedPassword"
android:text="Hashed Password"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/_50sdp"
android:textSize="@dimen/_20sdp"
/>
</RelativeLayout>
</RelativeLayout>
我的密码Class:
@Entity
public class Password {
@PrimaryKey(autoGenerate = true)
public int uid;
@ColumnInfo(name = "app_name")
public String app_name;
@ColumnInfo(name = "hashed_password")
public String hashed_password;
}
谢谢!
I think I should make a adapter for my listview but I don't know how to make it.
您可以使用内置适配器,例如 SimpleCursorAdapter(设计用于游标)。您可以指定布局。
使用 SimpleCursorAdapter 的唯一问题是您需要一个 Cursor,而 Room 通常不提供。但是,也许考虑以下工作示例,它通过 getAllPasswords
.
从提取中创建一个 MatrixCursor
该示例使用您的 密码 实体和您的 custom_listview.xml 不变。
然而,PasswordDao 已被修改(见评论)为:-
@Dao
public interface PasswordDAO {
@Query("SELECT * FROM password")
List<Password> getAllPasswords();
/* can't do as insufficient data to build Password objects
@Query("SELECT hashed_password FROM password")
ArrayList<Password> getAllHashedPasswords();
*/
/* Likewise
@Query("SELECT app_name FROM password")
ArrayList<Password> getAllAppNames();
*/
/* Likewise
@Query("SELECT uid FROM password")
ArrayList<Password> getAllIDs();
*/
@Insert
void insertUser(Password... passwords);
@Delete
void delete(Password password);
}
@Database class PasswordDatabase如下:-
@Database(entities = {Password.class},version =1,exportSchema = false)
abstract class PasswordDatabase extends RoomDatabase {
abstract PasswordDAO getDao();
private static volatile PasswordDatabase instance = null;
static PasswordDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context, PasswordDatabase.class,"password.db")
.allowMainThreadQueries()
.build();
}
return instance;
}
}
- 注意到为了方便和简洁起见,使用了 .allowMainThreadQueries。
MainActivity 的布局 activity_main.xml 是:-
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" >
</TextView>
<ListView
android:id="@+id/myListView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</androidx.appcompat.widget.LinearLayoutCompat>
- 即已添加 ListView
最后把它放在 MainActivity :-
public class MainActivity extends AppCompatActivity {
ListView myListView;
PasswordDatabase db;
PasswordDAO dao;
Cursor csr;
SimpleCursorAdapter sca;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = this.findViewById(R.id.myListView);
db = PasswordDatabase.getInstance(this);
dao = db.getDao();
/* add some testing data */
Password p1 = new Password();
p1.uid = 0;
p1.hashed_password = "hashpassword1";
p1.app_name = "App1";
Password p2 = new Password();
p2.uid = 0;
p2.hashed_password = "hashpassword2";
p2.app_name = "App2";
dao.insertUser(p1,p2);
setUpOrRefreshListView();
}
/* As it says setup or refresh the ListView */
private void setUpOrRefreshListView() {
csr = getCursor();
if (sca == null) {
sca = new SimpleCursorAdapter(
this,
R.layout.custom_listview,csr,
new String[]{"app_name","hashed_password"},
new int[]{R.id.customListView_AppName,R.id.customListView_HashedPassword},
0
);
myListView.setAdapter(sca);
/* BONUS handle Long Click of an Item in the ListView
in this case just Toast info
*/
myListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@SuppressLint("Range")
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(
view.getContext(),
"You long-clicked password with AppName = "
+ csr.getString(csr.getColumnIndex("app_name"))
+ " Hash = " + csr.getString(csr.getColumnIndex("hashed_password"))
+ " UID = " + l,
Toast.LENGTH_SHORT
).show();
return true;
}
});
} else {
sca.swapCursor(csr);
}
}
/* Gets all the passwords using getAllPassswords and creates a MatrixCursor */
private Cursor getCursor() {
List<Password> passwords = dao.getAllPasswords();
/* NOTE that as Cursor Adapters required a column named _ID (as per BaseColumns._ID)
the first column has been renamed accordingly
*/
MatrixCursor mxcsr = new MatrixCursor(new String[]{
BaseColumns._ID,
"app_name",
"hashed_password"},
0
);
for (Password p: dao.getAllPasswords()) {
mxcsr.addRow(new Object[]{p.uid,p.app_name,p.hashed_password});
}
return mxcsr;
}
/* If resuming this activity then refresh the ListView */
@Override
protected void onResume() {
super.onResume();
setUpOrRefreshListView();
}
/* if the activity is detsroyed then close the Cursor */
@Override
protected void onDestroy() {
super.onDestroy();
csr.close();
}
}
如果以上是第一次 运行 那么:-
- if 运行 将再添加两行,依此类推。尽管行有 App1 和 App2 等,但 uid 会有所不同。
我正在 android 上使用 Room Database 创建一个密码管理器。我想使用自定义 ListView,但找不到任何方法将我的房间数据库连接到自定义列表视图布局。我想我应该为我的列表视图制作一个适配器,但我不知道如何制作。寻找它,但无法做到。我该怎么做?
我通过以下方式获取数据库列表:
AppDatabase db = AppDatabase.getDbInstance(this.getApplicationContext());
List<Password> passwordList = db.passwordDAO().getAllPasswords();
我的道:
@Dao
public interface PasswordDAO {
@Query("SELECT * FROM password")
List<Password> getAllPasswords();
@Query("SELECT hashed_password FROM password")
ArrayList<Password> getAllHashedPasswords();
@Query("SELECT app_name FROM password")
ArrayList<Password> getAllAppNames();
@Query("SELECT uid FROM password")
ArrayList<Password> getAllIDs();
@Insert
void insertUser(Password... passwords);
@Delete
void delete(Password password);
我的自定义 ListView 布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/_80sdp"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="App Name"
android:id="@+id/customListView_AppName"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/_10sdp"
android:textSize="@dimen/_20sdp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/customListView_HashedPassword"
android:text="Hashed Password"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/_50sdp"
android:textSize="@dimen/_20sdp"
/>
</RelativeLayout>
</RelativeLayout>
我的密码Class:
@Entity
public class Password {
@PrimaryKey(autoGenerate = true)
public int uid;
@ColumnInfo(name = "app_name")
public String app_name;
@ColumnInfo(name = "hashed_password")
public String hashed_password;
}
谢谢!
I think I should make a adapter for my listview but I don't know how to make it.
您可以使用内置适配器,例如 SimpleCursorAdapter(设计用于游标)。您可以指定布局。
使用 SimpleCursorAdapter 的唯一问题是您需要一个 Cursor,而 Room 通常不提供。但是,也许考虑以下工作示例,它通过 getAllPasswords
.
该示例使用您的 密码 实体和您的 custom_listview.xml 不变。
然而,PasswordDao 已被修改(见评论)为:-
@Dao
public interface PasswordDAO {
@Query("SELECT * FROM password")
List<Password> getAllPasswords();
/* can't do as insufficient data to build Password objects
@Query("SELECT hashed_password FROM password")
ArrayList<Password> getAllHashedPasswords();
*/
/* Likewise
@Query("SELECT app_name FROM password")
ArrayList<Password> getAllAppNames();
*/
/* Likewise
@Query("SELECT uid FROM password")
ArrayList<Password> getAllIDs();
*/
@Insert
void insertUser(Password... passwords);
@Delete
void delete(Password password);
}
@Database class PasswordDatabase如下:-
@Database(entities = {Password.class},version =1,exportSchema = false)
abstract class PasswordDatabase extends RoomDatabase {
abstract PasswordDAO getDao();
private static volatile PasswordDatabase instance = null;
static PasswordDatabase getInstance(Context context) {
if (instance == null) {
instance = Room.databaseBuilder(context, PasswordDatabase.class,"password.db")
.allowMainThreadQueries()
.build();
}
return instance;
}
}
- 注意到为了方便和简洁起见,使用了 .allowMainThreadQueries。
MainActivity 的布局 activity_main.xml 是:-
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" >
</TextView>
<ListView
android:id="@+id/myListView"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</androidx.appcompat.widget.LinearLayoutCompat>
- 即已添加 ListView
最后把它放在 MainActivity :-
public class MainActivity extends AppCompatActivity {
ListView myListView;
PasswordDatabase db;
PasswordDAO dao;
Cursor csr;
SimpleCursorAdapter sca;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myListView = this.findViewById(R.id.myListView);
db = PasswordDatabase.getInstance(this);
dao = db.getDao();
/* add some testing data */
Password p1 = new Password();
p1.uid = 0;
p1.hashed_password = "hashpassword1";
p1.app_name = "App1";
Password p2 = new Password();
p2.uid = 0;
p2.hashed_password = "hashpassword2";
p2.app_name = "App2";
dao.insertUser(p1,p2);
setUpOrRefreshListView();
}
/* As it says setup or refresh the ListView */
private void setUpOrRefreshListView() {
csr = getCursor();
if (sca == null) {
sca = new SimpleCursorAdapter(
this,
R.layout.custom_listview,csr,
new String[]{"app_name","hashed_password"},
new int[]{R.id.customListView_AppName,R.id.customListView_HashedPassword},
0
);
myListView.setAdapter(sca);
/* BONUS handle Long Click of an Item in the ListView
in this case just Toast info
*/
myListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@SuppressLint("Range")
@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(
view.getContext(),
"You long-clicked password with AppName = "
+ csr.getString(csr.getColumnIndex("app_name"))
+ " Hash = " + csr.getString(csr.getColumnIndex("hashed_password"))
+ " UID = " + l,
Toast.LENGTH_SHORT
).show();
return true;
}
});
} else {
sca.swapCursor(csr);
}
}
/* Gets all the passwords using getAllPassswords and creates a MatrixCursor */
private Cursor getCursor() {
List<Password> passwords = dao.getAllPasswords();
/* NOTE that as Cursor Adapters required a column named _ID (as per BaseColumns._ID)
the first column has been renamed accordingly
*/
MatrixCursor mxcsr = new MatrixCursor(new String[]{
BaseColumns._ID,
"app_name",
"hashed_password"},
0
);
for (Password p: dao.getAllPasswords()) {
mxcsr.addRow(new Object[]{p.uid,p.app_name,p.hashed_password});
}
return mxcsr;
}
/* If resuming this activity then refresh the ListView */
@Override
protected void onResume() {
super.onResume();
setUpOrRefreshListView();
}
/* if the activity is detsroyed then close the Cursor */
@Override
protected void onDestroy() {
super.onDestroy();
csr.close();
}
}
如果以上是第一次 运行 那么:-
- if 运行 将再添加两行,依此类推。尽管行有 App1 和 App2 等,但 uid 会有所不同。