Hongmeng App: Multi-device Alarm Clock Development Tutorial (6)

Database development and joint debugging

Before this section, we have completed the development of all setting pages. In this section, we will develop the operation of the ClockManager relational database, realize the persistence of adding, deleting, modifying and checking the clock, and debug all the previous interfaces in parallel. Verify the creation of the alarm clock on the real machine. modify, display and delete.

1. Improve the ClockManager class to realize the addition, deletion, modification and query of the alarm clock database

1. HarmonyOs has a built-in relational database. Because this application only needs host settings and timing operations, it only needs to implement a relational database instead of a distributed database. First, you need to add a Data Ability named ClockDataAbility, which defines the table name and columns of the alarm clock table, and writes the SQL for creating the table in onCreate.

public class ClockDataAbility extends Ability {
    private static final String TAG = ClockDataAbility.class.getName();
    public static final String DB_NAME = "crazyclock.db";
    public static final String DB_TAB_NAME = "crazyclock";
    public static final String DB_COLUMN_ID = "id";
    public static final String DB_COLUMN_NAME = "name";
    public static final String DB_COLUMN_BELL = "bell";
    public static final String DB_COLUMN_HOUR = "hour";
    public static final String DB_COLUMN_MINUTE = "minute";
    public static final String DB_COLUMN_DURATION = "duration";
    public static final String DB_COLUMN_ENABLE = "enable";
    private static final int DB_VERSION = 1;
    private StoreConfig config = StoreConfig.newDefaultConfig(DB_NAME);
    private RdbStore rdbStore;
    private RdbOpenCallback rdbOpenCallback = new RdbOpenCallback() {
        @Override
        public void onCreate(RdbStore store) {
            store.executeSql("create table if not exists "
                    + DB_TAB_NAME + " ("
                    + DB_COLUMN_ID + " integer primary key, "
                    + DB_COLUMN_NAME + " text not null, "
                    + DB_COLUMN_BELL + " integer not null, "
                    + DB_COLUMN_HOUR + " integer not null, "
                    + DB_COLUMN_MINUTE + " integer not null, "
                    + DB_COLUMN_DURATION + " integer not null, "
                    + DB_COLUMN_ENABLE + " boolean)");
        }
        private int duration;
        private int strategy;
        private boolean isEnable;
        @Override
        public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {
        }
    };
    
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        LogUtil.info(TAG, "ClockDataAbility onStart");
        DatabaseHelper databaseHelper = new DatabaseHelper(this);
        rdbStore = databaseHelper.getRdbStore(config, DB_VERSION, rdbOpenCallback, null);
    }
}
  1. Add functions in ClockDataAbility to realize the persistent addition, deletion, modification and query of relational databases. You can refer to the official documents .

   @Override
    public int insert(Uri uri, ValuesBucket value) {
        LogUtil.info(TAG, "ClockDataAbility insert");
        String path = uri.getLastPath();
        if (!DB_TAB_NAME.equals(path)) {
            LogUtil.info(TAG, "DataAbility insert path is not matched");
            return -1;
        }
        ValuesBucket values = new ValuesBucket();
        values.putString(DB_COLUMN_NAME, value.getString(DB_COLUMN_NAME));
        values.putInteger(DB_COLUMN_BELL, value.getInteger(DB_COLUMN_BELL));
        values.putInteger(DB_COLUMN_HOUR, value.getInteger(DB_COLUMN_HOUR));
        values.putInteger(DB_COLUMN_MINUTE, value.getInteger(DB_COLUMN_MINUTE));
        values.putInteger(DB_COLUMN_DURATION, value.getInteger(DB_COLUMN_DURATION));
        values.putBoolean(DB_COLUMN_ENABLE, value.getBoolean(DB_COLUMN_ENABLE));
        int index = (int) rdbStore.insert(DB_TAB_NAME, values);
        DataAbilityHelper.creator(this, uri).notifyChange(uri);//todo ?
        return index;
    }
    @Override
    public int delete(Uri uri, DataAbilityPredicates predicates) {
        RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, DB_TAB_NAME);
        int index = rdbStore.delete(rdbPredicates);
        DataAbilityHelper.creator(this, uri).notifyChange(uri);
        return index;
    }
    @Override
    public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
        RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, DB_TAB_NAME);
        int index = rdbStore.update(value, rdbPredicates);
        LogUtil.info(TAG, "update: " + index);
        DataAbilityHelper.creator(this, uri).notifyChange(uri);
        return index;
    }
    @Override
    public FileDescriptor openFile(Uri uri, String mode) {
        return null;
    }
    @Override
    public String[] getFileTypes(Uri uri, String mimeTypeFilter) {
        return new String[0];
    }
    @Override
    public PacMap call(String method, String arg, PacMap extras) {
        return null;
    }
    @Override
    public String getType(Uri uri) {
        return null;
    }

1.3 ClockManager implements the encapsulation of ClockDataAbility, operates with Clock as the object, and provides a singleton object externally. Among them, BASE_URI should be consistent with the complete class name of ClockDataAbility.

ClockDataAbility.java

package com.madixin.clock.setting.manager;
import com.madixin.clock.common.util.LogUtil;
import com.madixin.clock.setting.ability.ClockDataAbility;
import com.madixin.clock.setting.model.Clock;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.app.Context;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.rdb.ValuesBucket;
import ohos.data.resultset.ResultSet;
import ohos.utils.net.Uri;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
public class ClockManager {
    private static final String TAG = ClockManager.class.getName();
    private static ClockManager instance;
    private static final String BASE_URI = "dataability:///com.madixin.clock.setting.ability.ClockDataAbility";
    private Context context;
    private DataAbilityHelper databaseHelper;
    private static final String DATA_PATH = "/crazyclock";
    private ClockManager(Context context) {
        this.context = context;
        this.databaseHelper = DataAbilityHelper.creator(context);
    }
    private List<Clock> clockList = new LinkedList<>();
    public static ClockManager getInstance(Context context) {
        if (instance == null) {
            instance = new ClockManager(context);
        }
        return instance;
    }
    /**
     * 获取所有闹钟
     * @return 闹钟列表
     */
    public List<Clock> getAllClocks() {
        this.clockList = new LinkedList<>();
        String[] columns = new String[]{ClockDataAbility.DB_COLUMN_ID,
                ClockDataAbility.DB_COLUMN_NAME, ClockDataAbility.DB_COLUMN_BELL, ClockDataAbility.DB_COLUMN_HOUR,
                ClockDataAbility.DB_COLUMN_MINUTE, ClockDataAbility.DB_COLUMN_DURATION, ClockDataAbility.DB_COLUMN_ENABLE};
        // 构造查询条件
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        //predicates.between(DB_COLUMN_AGE, 15, 40);
        try {
            ResultSet resultSet = databaseHelper.query(Uri.parse(BASE_URI + DATA_PATH),
                    columns, predicates);
            if (resultSet == null || resultSet.getRowCount() == 0) {
                LogUtil.info(TAG, "query: resultSet is null or no result found");
                return this.clockList;
            }
            resultSet.goToFirstRow();
            do {
                Clock clock = new Clock();
                clock.setId(resultSet.getInt(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_ID)));
                clock.setName(resultSet.getString(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_NAME)));
                clock.setBell(resultSet.getInt(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_BELL)));
                clock.setHour(resultSet.getInt(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_HOUR)));
                clock.setMinute(resultSet.getInt(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_MINUTE)));
                clock.setDuration(resultSet.getInt(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_DURATION)));
                clock.setEnable(resultSet.getInt(resultSet.getColumnIndexForName(ClockDataAbility.DB_COLUMN_ENABLE)) == 1);
                this.clockList.add(clock);
                LogUtil.info(TAG, "query: clock :" + clock);
            } while (resultSet.goToNextRow());
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            LogUtil.error(TAG, "query: dataRemote exception | illegalStateException" + exception.getMessage());
        }
        LogUtil.info(TAG, "getAllClocks : size= " + this.clockList.size());
        return this.clockList;
    }
    /**
     * 创建新闹钟
     * @param clock clock
     */
    public void createNewClock(Clock clock) {
        ValuesBucket valuesBucket = new ValuesBucket();
        valuesBucket.putString(ClockDataAbility.DB_COLUMN_NAME, clock.getName());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_BELL, clock.getBell());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_HOUR, clock.getHour());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_MINUTE, clock.getMinute());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_DURATION, clock.getDuration());
        valuesBucket.putBoolean(ClockDataAbility.DB_COLUMN_ENABLE, clock.isEnable());
        try {
            int id = databaseHelper.insert(Uri.parse(BASE_URI + DATA_PATH), valuesBucket);
            if (id == -1) {
                LogUtil.error(TAG, "fail to insert");
            } else {
                LogUtil.info(TAG, "success to insert id=" + id);
            }
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            LogUtil.error(TAG, "insert: dataRemote exception | illegalStateException" + exception.getMessage());
        }
    }
    /**
     * 删除闹钟
     * @param clock clock
     * @return
     */
    public int deleteClock(Clock clock) {
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.contains(ClockDataAbility.DB_COLUMN_ID, String.valueOf(clock.getId()));
        try {
            return databaseHelper.delete(Uri.parse(BASE_URI + DATA_PATH), predicates);
        } catch (DataAbilityRemoteException e) {
            LogUtil.error(TAG, "delete: dataRemote exception | illegalStateException" + e.getMessage());
        }
        return -1;
    }
    /**
     * 返回列表第几个的闹钟数据
     *
     * @param itemId 列表项
     * @return Optional<Clock>
     */
    public Optional<Clock> getClockByItemId(int itemId) {
        if (itemId > this.clockList.size() || this.clockList.size() == 0) {
            return Optional.empty();
        }
        return Optional.ofNullable(this.clockList.get(itemId));
    }
    /**
     * 更新闹钟
     * @param clock clock
     * @return
     */
    public int updateClock(Clock clock) {
        DataAbilityPredicates predicates = new DataAbilityPredicates();
        predicates.contains(ClockDataAbility.DB_COLUMN_ID, String.valueOf(clock.getId()));
        ValuesBucket valuesBucket = new ValuesBucket();
        valuesBucket.putString(ClockDataAbility.DB_COLUMN_NAME, clock.getName());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_BELL, clock.getBell());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_HOUR, clock.getHour());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_MINUTE, clock.getMinute());
        valuesBucket.putInteger(ClockDataAbility.DB_COLUMN_DURATION, clock.getDuration());
        valuesBucket.putBoolean(ClockDataAbility.DB_COLUMN_ENABLE, clock.isEnable());
        try {
            int id = databaseHelper.update(Uri.parse(BASE_URI + DATA_PATH), valuesBucket, predicates);
            if (id == -1) {
                LogUtil.error(TAG, "fail to insert");
            } else {
                LogUtil.info(TAG, "success to insert id=" + id);
                return id;
            }
        } catch (DataAbilityRemoteException | IllegalStateException exception) {
            LogUtil.error(TAG, "insert: dataRemote exception | illegalStateException" + exception.getMessage());
        }
        return -1;
    }
}

2. Implement the main page list switch to control whether the alarm clock is turned on

2.1. Add a custom interface SwitchStateChangedListener in ListViewClockItemProvider.

    public interface SwitchStateChangedListener {
        public void onSwitchStateChanged(Button button, boolean isEnable, int position);
    }
    private SwitchStateChangedListener switchStateChangedListener;

2.2 Publish the change event of Switch to the slice.

        viewHolder.switchState.setCheckedStateChangedListener((button, isEnable) -> {
            switchStateChangedListener.onSwitchStateChanged(button, isEnable, position);
        });

2.3 Listen to the Switch switching event in the initListContainer method of MainAbilitySlice.java, and update the database.

        // Switch切换按钮
        listViewClockItemProvider.setSwitchStateChangedListener(((button, isEnable, position) -> {
            Optional<Clock> clockOptional = ClockManager.getInstance(this.getApplicationContext()).getClockByItemId(position);
            if (clockOptional.isPresent()) {
                Clock curClock = clockOptional.get();
                curClock.setEnable(isEnable);
                ClockManager.getInstance(this.getApplicationContext()).updateClock(curClock);
            }
        }));

3. Summary

After completing the database joint debugging operation in this section, the alarm setting function of the entire application has been fully developed. After debugging on the simulator, it is recommended to use the real machine P40 debugging to verify the function, and the data after each operation in the real machine will be saved in the database of the real machine. Real machine debugging requires signature and other steps, you can refer to the official document .

In the next step, we will develop the alarm clock interface in the alarm clock FA.

4. Code address:

github , commit record: e6611286ebf042ec060ef999d0c12f9f77a2b965

 

おすすめ

転載: blog.csdn.net/sd2131512/article/details/117572339