web-dev-qa-db-ja.com

Flutter:大規模なデータベース操作の進行中のUIのフリーズを回避

[〜#〜] update [〜#〜](2020年7月15日)

mFeinsteinの応答は、今のところ、私に最初の受け入れられる解決策を与える唯一の答えです。


[〜#〜]質問[〜#〜]

私がやろうとしていることを行うための最良のアプローチは何ですか?

  1. 非同期モードでのWebサービスの呼び出し
  2. 解析応答
  3. 大規模なデータベース操作の実行

不確定なプログレスバーのように、プログレスアニメーションをフリーズすることなく、これらすべてが可能です。

1点目と2点目は問題ありません。大規模なデータベース挿入が実行されているときに、問題が3番目に発生します。そして、私はまだこれを実装するための正しい方法がどのようになっているのか理解していません。

明確にするためのいくつかの疑似コード

I(ダイアログが表示され、進行状況バーが実行されます...)

_void callWS() async {
    MyProgressDialog _dialog = DialogHelper.showMyProgressDialog(_context, "Data", "Loading...");
    await getDataFromService();
    _dialog.close();
  }
_

接続(プログレスバーでフリーズは発生しません)

_   static Future<void> getDataFromService() async {
    String uri = MY_URI;
    String wsMethod = MY_WS_METHOD;
    String wsContract = MY_WS_CONTRACT;

    SoapObject myRequest = SoapObject.fromSoapObject(namespace: my_namespace, name: wsMethod);

    MyConnectionResult response = await _openMyConnection(myRequest, uri, wsContract, wsMethod);
    if (response.result == MyResultEnum.OK) {
      await _parseResponse(response.data);
    }
  }
_

データベース(プログレスバーでフリーズが発生します)

_  static Future<void> _parseResponse(xml.XmlElement elements) async {
    Database db = await MyDatabaseHelper.openConnection();
    db.transaction((tx) async {
      Batch batch = tx.batch();
      for (xml.XmlElement oi in elements.children) {
        int id = int.parse(oi.findElements("ID").first.text);
        String name = oi.findElements("NAME").first.text;

        DatabaseHelper.insertElement(
          tx,
          id: id,
          name: name,
        );
      }
      batch.commit(noResult: true);
    });
  }
_

代替機能していません

「計算」関数のアプローチも見ましたが、db操作を呼び出すときに_sqflite package_に問題があるようです。例えば:

_  static Future<void> performDelete() async {
    Database db = await openMyConnection();
    compute(_performDeleteCompute, db);
  }

  static void _performDeleteCompute(Database db) async {
    db.rawQuery("DELETE MYTABLE");
  }

Console error:'
-> Unhandled Exception: Exception: ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized. 
-> If you are running an application and need to access the binary messenger before runApp() has been called (for example, during plugin initialization),
then you need to explicitly call the WidgetsFlutterBinding.ensureInitialized() first.
-> error defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.Dart:76:7)
    #1      defaultBinaryMessenger (package:flutter/src/services/binary_messenger.Dart:89:4)
    #2      MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.Dart:140:62)
    #3      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.Dart:146:35)
    #4      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.Dart:329:12)
    #5      invokeMethod (package:sqflite/src/sqflite_impl.Dart:17:13)
    #6      SqfliteDatabaseFactoryImpl.invokeMethod (package:sqflite/src/factory_impl.Dart:31:7)
    #7      SqfliteDatabaseMixin.invokeMethod (package:sqflite_common/src/database_mixin.Dart:287:15)
    #8      SqfliteDatabaseMixin.safeInvokeMethod.<anonymous closure> (package:sqflite_common/src/database_mixin.Dart:208:43)
    #9      wrapDatabaseException (package:sqflite/src/exception_impl.Dart:7:32)
    #10     SqfliteDatabaseFactoryImpl.wrapDatabaseException (package:sqflite/src/factory_impl.Dart:27:7)
    #11     SqfliteDatabaseMixin.safeInvokeMethod (package:sqflite_common/src/database_mixin.Dart:208:15)
    #12     SqfliteDatabaseMixin.txnRawQuery.<anonymous closure> (package:sqflite_common/src/database_mixin.Dart:394:36)
    #13     SqfliteDatabaseMixin.txnSynchronized.<anonymous closure> (package:sqflite_common/src/database_mixin.Dart:327:22)
    #14     BasicLock.synchronized (package:synchronized/src/basic_lock.Dart:32:26)
    #15     SqfliteDatabaseMixin.txnSynchronized (package:sqflite_common/src/database_mixin.Dart:323:33)
    #16     SqfliteDatabaseMixin.txnRawQuery (package:sqflite_common/src/database_mixin.Dart:393:12)
    #17     SqfliteDatabaseExecutorMixin._rawQuery (package:sqflite_common/src/database_mixin.Dart:126:15)
    #18     SqfliteDatabaseExecutorMixin.rawQuery (package:sqflite_common/src/database_mixin.Dart:120:12)
    #19     DatabaseHelper._performDeleteCompute(package:flutter_infocad/Database/DatabaseHelper.Dart:368:8)'
_

また、エラーログで提案されているように、runApp()の最初のようにWidgetsFlutterBinding.ensureInitialized()を明示的に呼び出しても何も起こりません。

6
kinghomer

分離と計算がサードパーティのライブラリで機能しないことがある flutter_isolate を使用する必要がある

FlutterIsolateは、フラッタープラグインを使用できるフラッター内の分離の作成を許可します

0
Jim Chiu