#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
beforeaddRow
методом` getCursor».4. Пытался сделать и сделал это. Большое тебе спасибо, братан. Я ценю тебя.