Как подключить базу данных номеров к пользовательскому списку

#java #android #xml #android-room

#java #android #xml #android-room

Вопрос:

Я создаю менеджер паролей на Android с базой данных номеров. Я хочу использовать пользовательский список, но не смог найти никаких способов подключения базы данных моей комнаты к пользовательскому макету списка. Я думаю, что мне следует сделать адаптер для моего списка, но я не знаю, как это сделать. Искал его, но не смог найти. Как мне это сделать?

Я получаю список базы данных с помощью:

 AppDatabase db = AppDatabase.getDbInstance(this.getApplicationContext());  Listlt;Passwordgt; passwordList = db.passwordDAO().getAllPasswords();  

Мое Дао:

 @Dao public interface PasswordDAO {  @Query("SELECT * FROM password") Listlt;Passwordgt; getAllPasswords();  @Query("SELECT hashed_password FROM password") ArrayListlt;Passwordgt; getAllHashedPasswords();  @Query("SELECT app_name FROM password") ArrayListlt;Passwordgt; getAllAppNames();   @Query("SELECT uid FROM password")  ArrayListlt;Passwordgt; getAllIDs();  @Insert void insertUser(Password... passwords);  @Delete void delete(Password password);  

Мой пользовательский макет списка:

 lt;?xml version="1.0" encoding="utf-8"?gt; lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"gt;  lt;RelativeLayout  android:layout_width="match_parent"  android:layout_height="@dimen/_80sdp"  gt;   lt;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"  /gt;   lt;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"  /gt;  lt;/RelativeLayoutgt;  lt;/RelativeLayoutgt;  

Мой Класс Паролей:

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

Thanks!

Ответ №1:

I think I should make a adapter for my listview but I don’t know how to make it.

There are in built adapters that you can use, as an example a SimpleCursorAdapter (which are designed to work with Cursors). You can specify the layout.

The only issue with using the SimpleCursorAdapter is that you would need a Cursor, which Room doesn’t typically provide. However,perhaps consider the following working example, which creates a MatrixCursor from an extract via your getAllPasswords .

The example uses your Password entity and your custom_listview.xml unchanged.

Однако пароль был изменен (см. Комментарии), чтобы быть:-

 @Dao public interface PasswordDAO {   @Query("SELECT * FROM password")  Listlt;Passwordgt; getAllPasswords();   /* can't do as insufficient data to build Password objects  @Query("SELECT hashed_password FROM password")  ArrayListlt;Passwordgt; getAllHashedPasswords();  */   /* Likewise  @Query("SELECT app_name FROM password")  ArrayListlt;Passwordgt; getAllAppNames();  */    /* Likewise  @Query("SELECT uid FROM password")  ArrayListlt;Passwordgt; 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 был использован.

Планировка activity_main.xml для основной деятельности это :-

 lt;?xml version="1.0" encoding="utf-8"?gt; lt;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"gt;   lt;TextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Hello World!" gt;  lt;/TextViewgt;   lt;ListView  android:id="@ id/myListView"  android:layout_width="match_parent"  android:layout_height="wrap_content"gt;  lt;/ListViewgt;  lt;/androidx.appcompat.widget.LinearLayoutCompatgt;  
  • т. е. был добавлен просмотр списка

Наконец, полностью переведя его в основное состояние :-

 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(AdapterViewlt;?gt; 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() {  Listlt;Passwordgt; 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 будут разными.

Комментарии:

1. Спасибо тебе ооочень большое, это сработало! lt;3

2. Также, как я могу получить свой массив hashed_password, расшифровать (у меня есть функция дешифрования) и снова заменить его в listview?

3. При переходе к извлеченным паролям расшифруйте их из p.hashed_password back в p.hashed_password before addRow методом` getCursor».

4. Пытался сделать и сделал это. Большое тебе спасибо, братан. Я ценю тебя.