插入sqlite颤动而不冻结界面 [英] Insert sqlite flutter without freezing the interface

查看:78
本文介绍了插入sqlite颤动而不冻结界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用flutter在sqlite内存数据库中插入很多行(大约12k或更多).

我从API获取数据并使用计算函数来处理来自Json的数据.现在,我需要将这些数据添加到内存中的数据库中,以便使用批处理事务.

  batchInsertEventSong(List< EventSong>行)异步{数据库db =等待instance.database;db.transaction((txn)异步{批次批次= txn.batch();用于(成排的var歌曲){Map< String,dynamic>行= {DatabaseHelper.columnIdSong:song.id,DatabaseHelper.columnTitle:song.title,DatabaseHelper.columnInterpreter:歌曲.解释器};batch.insert(表格,行);}batch.commit();}} 

但是此函数在插入过程中阻止了我的UI,我也尝试了计算,但是无法传递类db或类批处理.我没有弄清楚如何在另一个线程中执行此过程,或者(因为我不能使用隔离)在不阻塞我的UI的情况下执行.

有什么建议吗?

解决方案

2020年5月15日至15日

这行不通,请参阅:

  • 步骤1:将您的方法设为静态并使其无效

     静态batchInsertEventSong(List< EventSong>行){数据库db =等待instance.database;db.transaction((txn)异步{批次批次= txn.batch();用于(成排的var歌曲){Map< String,dynamic>行= {DatabaseHelper.columnIdSong:song.id,DatabaseHelper.columnTitle:song.title,DatabaseHelper.columnInterpreter:歌曲.解释器};batch.insert(表格,行);}batch.commit();}} 

    第2步:创建新方法(通常但并非必需,为同名添加Async)

     将来的batchInsertEventSongAsync(List< EventSong>行){} 

    第3步:使用您的方法static调用compute并返回

     返回计算(batchInsertEventSong,行); 


    步骤[1,2,3]代码审核

     将来的batchInsertEventSongAsync(List< EventSong>行){返回compute(_batchInsertEventSong,行);}静态_batchInsertEventSong(List< EventSong>行){数据库db =等待instance.database;db.transaction((txn)异步{批次批次= txn.batch();用于(成排的var歌曲){Map< String,dynamic>行= {DatabaseHelper.columnIdSong:song.id,DatabaseHelper.columnTitle:song.title,DatabaseHelper.columnInterpreter:歌曲.解释器};batch.insert(表格,行);}batch.commit();}} 


    完整代码

      import'dart:async';导入'package:flutter/foundation.dart';导入'package:flutter/material.dart';void main()=>runApp(MyApp());MyApp类扩展了StatelessWidget {//此小部件是您的应用程序的根.@override窗口小部件build(BuildContext context){返回MaterialApp(标题:"Flutter演示",主题:ThemeData(primarySwatch:Colors.blue,),主页:脚手架(正文:MyHomePage(标题:"Flutter演示首页")),);}}类MyHomePage扩展了StatefulWidget {MyHomePage({Key key,this.title}):超级(key:key);最终的字符串标题;@override_MyHomePageState createState()=>_MyHomePageState();}类_MyHomePageState扩展State< MyHomePage>{@override窗口小部件build(BuildContext context){返回脚手架(appBar:AppBar(标题:文本(widget.title),),身体:中心(子:列(mainAxisAlignment:MainAxisAlignment.center,子代:< Widget> [FlatButton.icon(图标:Icon(Icons.backup),标签:文字(长时间使用"),onPressed:()异步{var rows =等待RsetApi.getRawsAsync();等待Database._saveRaws(rows);},),FlatButton.icon(图标:Icon(Icons.backup),标签:文字("Short Opreation"),onPressed:(){Scaffold.of(context).hideCurrentSnackBar();Scaffold.of(context).showSnackBar(new SnackBar(内容:new Text(DateTime.now().toIso8601String()),));},),],),),);}}类RsetApi {静态Future< List< EventSong>>getRawsAsync(){返回compute(_getRaws,null);}静态List< EventSong>_getRaws(pram1){var rows = List< EventSong>();对于(var i = 1; i< 12000; i ++){rows.add(EventSong(i));print(获取原始文件" +(i/12000).toString());}返回行;}}类数据库{静态Future saveRawsAsync(List< EventSong>行){返回compute(_saveRaws,行);}静态_saveRaws(List< EventSong>行){for(var i = 1; i< rows.length; i ++){print(保存原始数据" +(i/rows.length).toString());}}}EventSong类{int id;EventSong(this.id);} 

    参考:

    非重要引用:

    I'm trying to insert a lot of rows (about 12k or more) in a sqlite memory database using flutter.

    I get data from the API and use a compute function in order to process data from Json. Now I need to add these data to a database in memory, in order to do so I use a transaction with a batch.

    batchInsertEventSong(List<EventSong> rows) async {
       Database db = await instance.database;
       db.transaction((txn) async {
          Batch batch = txn.batch();
          for (var song in rows) {
             Map<String, dynamic> row = {
               DatabaseHelper.columnIdSong: song.id,
               DatabaseHelper.columnTitle: song.title,
               DatabaseHelper.columnInterpreter: song.interpreter
             };
             batch.insert(table, row);
           }
          batch.commit();
       }
    }
    

    But this function is blocking my UI during insertions, I tried also with compute but I can't pass the class db or the class batch. I hadn't clear how to execute this process in another thread or (since I can't use isolates) executing without blocking my UI.

    Any advice?

    解决方案

    Update 2020 - 05 - 15

    this will not work see :


    Note : full code available on the end

    Step 1 : make your method static and make it void

      static batchInsertEventSong(List<EventSong> rows) {
        Database db = await instance.database;
        db.transaction((txn) async {
            Batch batch = txn.batch();
            for (var song in rows) {
                Map<String, dynamic> row = {
                DatabaseHelper.columnIdSong: song.id,
                DatabaseHelper.columnTitle: song.title,
                DatabaseHelper.columnInterpreter: song.interpreter
                };
                batch.insert(table, row);
            }
            batch.commit();
        }
      }
    

    Step 2 : create new method (usually but not required add Async for the same name)

      Future batchInsertEventSongAsync(List<EventSong> rows) {
    
      }
    

    Step 3 : call compute with your method static and return

      return compute(batchInsertEventSong, rows);
    


    Step [1,2,3] code review

      Future batchInsertEventSongAsync(List<EventSong> rows) {
        return compute(_batchInsertEventSong, rows);
      }
    
      static _batchInsertEventSong(List<EventSong> rows) {
        Database db = await instance.database;
        db.transaction((txn) async {
            Batch batch = txn.batch();
            for (var song in rows) {
                Map<String, dynamic> row = {
                DatabaseHelper.columnIdSong: song.id,
                DatabaseHelper.columnTitle: song.title,
                DatabaseHelper.columnInterpreter: song.interpreter
                };
                batch.insert(table, row);
            }
            batch.commit();
        }
      }
    


    Full Code

    import 'dart:async';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(body: MyHomePage(title: 'Flutter Demo Home Page')),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                FlatButton.icon(
                  icon: Icon(Icons.backup),
                  label: Text("Long Opreation"),
                  onPressed: () async {
                    var rows = await RsetApi.getRawsAsync();
                    await Database._saveRaws(rows);
                  },
                ),
                FlatButton.icon(
                  icon: Icon(Icons.backup),
                  label: Text("Short Opreation"),
                  onPressed: () {
                    Scaffold.of(context).hideCurrentSnackBar();
                    Scaffold.of(context).showSnackBar(new SnackBar(
                      content: new Text(DateTime.now().toIso8601String()),
                    ));
                  },
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class RsetApi {
      static Future<List<EventSong>> getRawsAsync() {
        return compute(_getRaws, null);
      }
    
      static List<EventSong> _getRaws(pram1) {
        var rows = List<EventSong>();
        for (var i = 1; i < 12000; i++) {
          rows.add(EventSong(i));
          print("fetching raws " + (i / 12000).toString());
        }
        return rows;
      }
    }
    
    class Database {
      static Future saveRawsAsync(List<EventSong> rows) {
        return compute(_saveRaws, rows);
      }
    
      static _saveRaws(List<EventSong> rows) {
        for (var i = 1; i < rows.length; i++) {
          print("saving raws " + (i / rows.length).toString());
        }
      }
    }
    
    class EventSong {
      int id;
      EventSong(this.id);
    }
    

    Ref:

    non-important Ref:

    这篇关于插入sqlite颤动而不冻结界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆