В реализации базы данных Android Room проблема использования allowMainThreadQueries для небольших таблиц? - PullRequest
0 голосов
/ 17 января 2020

Обучаясь Android, я создал приложение для жителей кондо-комплекса, чтобы найти утилиты для своего подразделения. Есть 4 таблицы; таблица единиц измерения (строки <100), таблица газа (строки <100), таблица electri c (строки <100) и таблица водяных клапанов (строки <200). Пользователь изначально взаимодействует с двумя счетчиками; 1, чтобы выбрать их здание, а другой их блок. Эта информация используется для извлечения данных из таблицы единиц измерения для связи с другими таблицами. В верхней части счетчиков есть флажок, чтобы установить единицу измерения как «вашу», чтобы приложение открывалось с выбранным блоком в счетчиках. Обновление таблицы единиц измерения для «ваших» - единственное изменение, которое пользователь внесет в таблицы. Нет добавления строк или других обновлений, поэтому таблицы имеют статус c, так как новые утилиты будут добавляться ежедневно, не говоря уже о раз в год. </p>

Моя первая реализация была с действиями (без фрагментов) и SQLiteAssetHelper (расширяет SQLiteOpenHelper). Работало нормально, все очень последовательно. Настройка «твоя» работает отлично.

Вторая реализация для фрагментов, чтобы в полной мере использовать емкость дисплея планшета. Также перенесен в комнату на базе данных MVVM (LiveData) для передачи данных для базы данных и фрагментов. Не использовал allowMainThreadQueries, за исключением модульного теста.

Пример кода для сущности объекта ниже.

    @Entity(tableName = "units")
public class Unit {

    @NonNull
    private int building;   // Building number or street address that contains the unit
                            //   4561, 4571, 4575, 4581 or 4591
    @NonNull
    private int unit;       // Unit number in the building, unit numbers repeat between buildings
    @NonNull
    private int stack;      // Identify's the stack in which the unit resides.  Last number of unit
                            //   is that unit's stack (i.e. unit 203 belongs to stack 3)
    @PrimaryKey(autoGenerate = false)
    @ColumnInfo(name = "unit_id")
    @NonNull
    private int unitId;     /* Combination of building and unit to make a unique identifier
                               (i.e. for building 4561 unit 203, unit ID is 4561203)
                               Note, building 4575 has a unit ID of 4575 since it has no units.
                            */
    @ColumnInfo(name = "stack_id")
    @NonNull
    private int stackId;    // Combination of building and stack to make a unique identifier
                            //   (i.e. for building 4561 unit 203, stack ID is 45613)
    @NonNull
    private int yours;      /* Indicator of whether the unit is yours or the unit the user wants
                               the app to start up with already selected.  Note that SQLite on
                               android does not have a boolean data type, so 0 is false, 1 is true.
                            */

Пример кода для единицы DAO ниже.

    @Dao
public interface UnitDao {

    @Insert
    void insert(Unit unit);

    @Query("SELECT * FROM units WHERE unit_id = :requestedUnitId")
    LiveData<Unit> getUnitByUnitId(int requestedUnitId);

    @Query("SELECT * FROM units WHERE yours = 1 LIMIT 1")
    LiveData<Unit> getYourUnit();

    @Update
    void setYourUnit(Unit unit);

    @Query("UPDATE units SET yours = 0 WHERE yours = 1")
    int clearYourUnit();

Пример кода для база данных ниже.

    private static SeaporteHoaDatabase instance;

public abstract UnitDao unitDao();
public abstract WaterValveDao waterValveDao();
public abstract ElectricMeterDao electricMeterDao();
public abstract GasMeterDao gasMeterDao();

public static synchronized SeaporteHoaDatabase getInstance(Context context) {

    /*
        When no database instance exists,
        1st, on first run, create the database from the assets directory
        2nd, migrates when necessary
        3rd, builds
     */
    if (instance == null) {
        instance = Room.databaseBuilder(context.getApplicationContext(),
                SeaporteHoaDatabase.class, DB_NAME)
                .createFromAsset("databases/" + DB_NAME)
                .fallbackToDestructiveMigration()
                .build();
    }

    return instance;
}

В модульном тестировании взаимодействие с таблицами работает хорошо, но я разрешаю запросы основного потока для LiveDataTestUtil, который также имеет встроенную задержку (wait).

In приложение, функциональные возможности для получения актуальной информации о полезности из таблиц газа, электричества c и водяных клапанов после выбора устройства работает нормально. Установка «твоего» в таблице единиц ведет себя странно. После установки «yours», закрытия приложения и перезапуска база данных не имеет его, и это первая проверка, которую делает приложение. Иногда возникает задержка, возможно, из-за фоновой обработки Room.

Пример кода для YourUnitFragment.

    @Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    tvYourSelectedBuilding = getView().findViewById(R.id.tvYourSelectedBuilding);
    tvYourSelectedUnit = getView().findViewById(R.id.tvYourSelectedUnit);
    tvYourInfo = getView().findViewById(R.id.tvYourInfo);
    tvYourPreviousHeader = getView().findViewById(R.id.tvYourPreviousHeader);
    tvYourPreviousBuilding = getView().findViewById(R.id.tvYourPreviousBuilding);
    tvYourPreviousUnit = getView().findViewById(R.id.tvYourPreviousUnit);

    btnYes = getView().findViewById(R.id.btnYourUnitYes);
    btnNo = getView().findViewById(R.id.btnYourUnitNo);

    /*
       Obtain the selected unit information
     */
    unitSelectionViewModel = ViewModelProviders.of(getActivity()).get(UnitSelectionViewModel.class);
    unitSelectionViewModel.getUnitSelected().observe(getViewLifecycleOwner(), new Observer<Unit>() {
        @Override
        public void onChanged(Unit unit) {
            yourUnit = unit;

            if (yourUnit != null) {
                tvYourSelectedBuilding.setText(String.format(Locale.US, "%d", yourUnit.getBuilding()));

                if (yourUnit.getBuilding() == 4575) {
                    tvYourSelectedUnit.setText(context.getString(R.string.unit_4575));
                } else {
                    tvYourSelectedUnit.setText(String.format(Locale.US, "%d", yourUnit.getUnit()));
                }
            }
        }
    });

Поскольку таблицы маленькие, будут разрешены запросы основного потока и удаление Функциональность LiveData сделает приложение более последовательным? Похоже, так и должно быть. Или Room все еще делает что-то на заднем плане?

...