2 . 数据持久化
由于 Flutter 仅接管了渲染层,真正涉及到存储等操作系统底层行为时,还需要依托于原生 Android、iOS. 三种数据持久化方法,即文件、SharedPreferences 与数据库 Flutter 提供了两种文件存储的目录,即临时(Temporary)目录与文档(Documents)目录:2.1 文件
需要引入: path_provider: ^1.6.4
//创建文件目录 Future<File> get _localFile async { final directory = await getApplicationDocumentsDirectory(); final path = directory.path; return File('$path/content.txt'); } //将字符串写入文件 Future<File> writeContent(String content) async { final file = await _localFile; return file.writeAsString(content); } //从文件读出字符串 Future<String> readContent() async { try { final file = await _localFile; String contents = await file.readAsString(); return contents; } catch (e) { return ""; } }
2.2 SharedPreferences
需要引入: shared_preferences: ^0.5.6+2
//读取SharedPreferences中key为counter的值 Future<int>_loadCounter() async { SharedPreferences prefs = await SharedPreferences.getInstance(); int counter = (prefs.getInt('counter') ?? 0); return counter; } //递增写入SharedPreferences中key为counter的值 Future<void>_incrementCounter() async { SharedPreferences prefs = await SharedPreferences.getInstance(); int counter = (prefs.getInt('counter') ?? 0) + 1; prefs.setInt('counter', counter); }
2.3 数据库
需要引入: sqflite: ^1.2.1
dbDemo() async { final Future<Database> database = openDatabase( //join是拼接路径分隔符 join(await getDatabasesPath(), 'student_database.db'), onCreate: (db, version) => db.execute( "CREATE TABLE students(id TEXT PRIMARY KEY,name TEXT,score INTEGER)"), onUpgrade: (db, oldVersion, newVersion) { //dosth for 升级 }, version: 1, ); Future<void> insertStudent(Student std) async { final Database db = await database; await db.insert( 'students', std.toJson(), //插入冲突策略,新的替换旧的 conflictAlgorithm: ConflictAlgorithm.replace, ); } //插入3个 await insertStudent(student1); await insertStudent(student2); await insertStudent(student3); Future<List<Student>> students() async { final Database db = await database; final List<Map<String, dynamic>> maps = await db.query('students'); return List.generate(maps.length, (i) => Student.fromJson(maps[i])); } ////读取出数据库中插入的Student对象集合 students().then((list) => list.forEach((s) => print(s.name))); //释放数据库资源 final Database db = await database; db.close(); }
3 . Flutter调原生
用AS单独打开Flutter项目中的Android工程,写代码,每次写完代码rebuild一下.然后想让Flutter代码能调到Android这边的代码,得重新运行. 如果AS run窗口不展示任何消息,可以使用 命令 flutter run lib/native/invoke_method.dart 执行dart,然后看错误消息. Flutter发起方法调用请求开始,请求经由唯一标识符指定的方法通道到达原生代码宿主,而原生代码宿主则通过注册对应方法实现,响应并处理调用请求.最后将执行结果通过消息通道,回传至Flutter. 方法通道是非线程安全的,需要在UI线程(Android或iOS的主线程)回调. 数据持久化,推送,摄像头,蓝牙等,都需要平台支持 轻量级解决方案: 方法通道机制 Method Channel 调用示例:class _MyHomePageState extends State<MyHomePage> { //声明MethodChannel static const platform = MethodChannel('com.xfhy.basic_ui/util'); handleButtonClick() async { bool result; //捕获 万一失败了呢 try { //异步等待,可能很耗时 等待结果 result = await platform.invokeMethod('isEmpty', "have data"); } catch (e) { result = false; } print('result : $result'); } } //Android代码 import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import io.flutter.plugins.GeneratedPluginRegistrant class MainActivity : FlutterActivity() { override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) //参考: https://flutter.dev/docs/development/platform-integration/platform-channels MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.xfhy.basic_ui/util").setMethodCallHandler { call, result -> //判断方法名是否支持 if (call.method == "isEmpty") { val arguments = call.arguments result.success(StringUtil.isEmpty(arguments as? String)) print("success") } else { //方法名暂不支持 result.notImplemented() print("fail") } } } }Android或者iOS的数据会被序列化成一段二进制格式的数据在通道中传输,当该数据传递到Flutter后,又会被反序列化成Dart语言中的类型.
查看更多关于Flutter 入门笔记(Part 8) 数据持久化与调原生方法的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did129215