【问题标题】:How to connect Room Database to Custom ListView如何将房间数据库连接到自定义 ListView
【发布时间】:2022-01-12 19:26:37
【问题描述】:

我正在使用 Room Database 在 android 上制作密码管理器。我想使用自定义列表视图,但找不到任何方法将我的房间数据库连接到自定义列表视图布局。我想我应该为我的列表视图制作一个适配器,但我不知道如何制作它。寻找它,但无法做到。我该怎么做?

我通过以下方式获取数据库列表:

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>

我的密码类:

@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;
}

谢谢!

【问题讨论】:

    标签: java android xml android-room


    【解决方案1】:

    我想我应该为我的列表视图制作一个适配器,但我不知道如何制作。

    您可以使用内置的适配器,例如 SimpleCursorAdapter(旨在与光标一起使用)。您可以指定布局。

    使用 SimpleCursorAdapter 的唯一问题是您需要一个光标,而 Room 通常不提供该光标。但是,也许考虑以下工作示例,它通过您的 getAllPasswords 从提取中创建一个 MatrixCursor。

    该示例使用您的 Password 实体和您的 custom_listview.xml 不变。

    但是,PasswordDao 已被修改(参见 cmets)为:-

    @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 类 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();
        }
    }
    

    当上面第一次运行时:-

    • 如果再次运行,则会再添加两行,依此类推。虽然行有 App1 和 App2 等,但 uid 会有所不同。

    【讨论】:

    • 太棒了,它成功了!
    • 另外我怎样才能得到我的 hashed_pa​​ssword 数组,解密(我有解密功能)并在 listview 中再次替换它?
    • 当在`getCursor`方法中的addRow之前从p.hashed_password解密回p.hashed_password提取的密码时。
    • 试图制作并做到了。太谢谢你了兄弟。我很感激你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-08
    • 1970-01-01
    相关资源
    最近更新 更多