插入sqlite颤动而不冻结界面 [英] Insert sqlite flutter without freezing the interface
问题描述
我正在尝试使用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);}
参考:
非重要引用:
-
sdk/文件.dart at 1c4ad14fa3a0a1d5ecea10e3b04befecee3ffbcb·dart-lang/sdk
-
sdk/file_impl.dart at 1c4ad14fa3a0a1d5ecea10e3b04befecee3ffbcb·dart-lang/sdk
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:
Flutter async : Beginner friendly guide for heavy lifting operations
sdk/file.dart at 1c4ad14fa3a0a1d5ecea10e3b04befecee3ffbcb · dart-lang/sdk
sdk/file_impl.dart at 1c4ad14fa3a0a1d5ecea10e3b04befecee3ffbcb · dart-lang/sdk
这篇关于插入sqlite颤动而不冻结界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!