web-dev-qa-db-fra.com

Flutter: évitez le gel de l'interface utilisateur lorsqu'une opération massive de base de données est en cours

UPDATE (15 juillet 2020)

La réponse de mFeinstein , pour l'instant, est la seule réponse qui me donne la première solution acceptable.


QUESTION

Je dois vous demander quelle est la meilleure approche pour faire ce que j'essaie de faire:

  1. Appeler un service Web en mode asynchrone
  2. Analyse de la réponse
  3. Effectuer des opérations de base de données massives

Tout cela sans geler l'animation de progression, comme la barre de progression indéterminée.

Il n'y a pas de problème au premier et au deuxième point. Le problème se produit au troisième, lorsqu'une insertion massive de base de données est en cours. Et je ne comprends pas encore comment est la bonne façon de mettre en œuvre ce genre de choses.

Un pseudo morceau de code pour clarifier

I (La boîte de dialogue s'affiche et la barre de progression s'exécute ...)

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

CONNEXION (Le gel ne se produit pas sur la barre de progression)

   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);
    }
  }

DATABASE (Freeze se produit sur la barre de progression)

  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);
    });
  }

NE FONCTIONNE PAS ALTERNATIVE

J'ai également vu l'approche de la fonction "compute", mais il semble qu'il y ait un problème dans sqflite package, Lorsque j'appelle une opération db. Par exemple:

  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)'

Et aussi en appelant explicitement la WidgetsFlutterBinding.ensureInitialized() comme premier dans runApp (), comme suggéré dans le journal des erreurs, rien ne se passe.

6
kinghomer

Isoler et calculer parfois ne fonctionnant pas avec une bibliothèque tierce, vous devez utiliser flutter_isolate

FlutterIsolate permet la création d'un isolat dans le flutter capable d'utiliser des plugins de flutter

0
Jim Chiu