如何在不锁定 UI 的情况下从 MySQLite 创建 SELECT?

How to make a SELECT from MySQLite without locking the UI?

我的 Activity 有问题,这是一个旧的 Android 项目,我正在尝试对其进行一些重构以提高应用程序的性能。

在 onCreate 中,我正在对来自不同表的数据执行 SELECT,如下所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
    LoadDataDB();
}

LoadDataDB 看起来像这样:

public void LoadDataDB() {
    myDB = DataBaseHandler.getInstance(this);

    menuConstructors = myDB.getMenu();
    items = myDB.getTasti();
    variantiConstructors = myDB.getVarianti();
    printers = myDB.getPrinters();

    if (myDB.getFamiglie().size() != 0) {
        myDB.deleteFam();
    }
    for (VariantiConstructor variantiConstructor : variantiConstructors) {
        if (!variantiConstructor.getFamiglie().equals("") && !variantiConstructor.getFamiglie().equals("0")) {
            myDB.insertFamiglie(variantiConstructor.getFamiglie());
        }
    }

    modelFamiglie = myDB.getFamiglie();

}

然后像getMenu这样的每个函数构建如下:

public ArrayList<MenuConstructor> getMenu() {
    database = this.getReadableDatabase();
    Cursor cursor = database.query(TABLE_MENU, null, null, null, null, null, null);
    ArrayList<MenuConstructor> contacts = new ArrayList<>();
    MenuConstructor contactModel;
    if (cursor.getCount() > 0) {
        for (int i = 0; i < cursor.getCount(); i++) {
            cursor.moveToNext();
            contactModel = new MenuConstructor(Integer.parseInt(cursor.getString(0)),
                    cursor.getString(1),cursor.getString(2),
                    cursor.getString(3));
            contacts.add(contactModel);
        }
    }
    cursor.close();
    database.close();
    return contacts;
}

当我打开 activity 时,它会锁定在 SplashScreen 上,直到获取数据为止,那么我如何重构该函数以使它们类似于不会锁定 UI 的异步功能?

要防止锁定 UI,您需要在另一个线程上执行 SELECT 查询。如果你会使用 Kotlin,我会推荐协程。

我开始使用 ThreadPoolExecutor 来完成这项任务。

您可以像这样在 DatabaseHandler 中创建 ThreadPoolExecutor 的静态实例:

public static final ExecutorService databaseWriteExecutor =  Executors.newFixedThreadPool(NUMBER_OF_THREADS);

并使用此实例执行您的查询。

要在另一个线程上执行指令,您可以使用:

DatabaseHandler.databaseWriteExecutor.execute(new Runnable() {
        @Override
        public void run() {
            LoadDataDB();
        }
    });

之后你只需要解决一个小问题。您需要在 UI 线程上执行 UI 更改。此问题的解决方案不止一种。

一个解决方案是创建 UI 线程循环程序的 Handler 并且 post 您的 UI 更改如下。

另一个解决方案是创建 LiveData 个实例并观察数据变化(观察者回调总是在 UI 线程上)