Dart的IO库包含了文件读写的相关类,它属于Dart语法标准的一部分,所以通过Dart IO库,无论是Dart VM下的脚本还是Flutter,都是通过Dart IO库来操作文件的,不过和Dart VM相比,Flutter有一个重要差异是文件系统路径不同,因为Dart VM是运行在PC或者服务器操作系统下,而Flutter是运行在移动操作系统中,他们的文件系统会有一些差异。
APP目录
Android和iOS的应用存储目录不同,PathProvider插件提供了一种平台透明的方式来访问设备文件系统的常用位置,该类当前支持访问两个文件系统位置:
- 临时目录:可以使用getTemporaryDirectory()来获取临时目录;系统可随时清除临时目录的文件。在iOS上对应NSTemporaryDirectory()的返回值。在Android上对应getCacheDir()返回值。
- 文档目录:可以使用getApplicationDocumentsDirectory()来获取应用程序的文档目录,该目录用于存储只有自己可以访问的文件。只有当应用程序被卸载时,系统才会清除该目录。在iOS上对应NSDocumentDirectory()。Android上对应AppData目录。
- 外部存储目录:可以使用getExternalStorageDirectory()来获取外部存储目录,如SD卡;由于iOS不支持外部目录,所以iOS下调用该方法会抛出UnsupportError异常,而在Android下时Android SDK中getExternalStorageDirectory返回值。
一旦Flutter应用程序有一个文件位置的引用,可以使用dart:io API来执行对文件系统的读写操作。
示例:
- 引入PathPrivider插件,在pubspec.yaml文件中添加声明:
path_provider: ^2.0.14
然后执行flutter packages get 获取一下,版本号会随着时间推移发生变化。
示例:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
class SSLFileManager extends StatefulWidget{
const SSLFileManager({Key? key}):super(key: key);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return SSLFileManagerState();
}
}
class SSLFileManagerState extends State<SSLFileManager>{
int counter = 0;
@override
void initState() {
// TODO: implement initState
super.initState();
readCounter().then((int value){
setState(() {
debugPrint("init counter $counter\n");
counter = value;
});
});
}
incrementCounter() async{
setState(() {
counter ++;
});
await (await getLocalFile()).writeAsString('$counter');
}
Future<File> getLocalFile() async{
String dir = (await getApplicationDocumentsDirectory()).path;
return File("$dir/counter.txt");
}
Future<int> readCounter() async{
try{
File file = await getLocalFile();
String contents = await file.readAsString();
return int.parse(contents);
} on FileSystemException{
return 0;
}
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: const Text("Flie IO"),
),
body: Center(
child: Text("Current num $counter"),
),
floatingActionButton: FloatingActionButton(
onPressed: incrementCounter,
tooltip: "Increment",
child: const Icon(Icons.add),
),
);
}
}
需要注意的是:
如果是刚引入path_provider库,可能会出现问题。
问题1:
- Unhandled Exception: MissingPluginException(No implementation found for method on channel
类似这种报错,不要慌,先百度查询一下资料,发现这个问题回复的答案各不相同,有的说是库的问题,有的说是安卓和iOS的通道。但是我们实际上啥都没有操作。所以怀疑不是以上说的问题。
处理方案:
- 关闭工程,然后打开终端,输入
flutter clean
flutter packages get
flutter run
选择设备
通常到这里,是可以正常运行设备的。但是也有可能出幺蛾子。
大致就是什么CocoaPods的问题。
那么是不是CocoaPods的问题?我们来看一下,找到iOS对应的工程,然后执行
pod install --no-repo-update
可以看到是有些库在更新。
这个时候去运行工程,工程是可以正常起来的。但是还是会报错。最后神奇的是使用Android Studio Run 会经常报错,但是debug运行是正常的,难道是因为我用的模拟器?Fuck!!!!!!,更神奇的是这个时候如果再去Run,又好了!!!
个人推测应该是缓存或者是热加载惹的祸,大家在遇到类似的问题时也可以用类似的方式去校验处理。。。。
最后验证了,如果出现类似使用了跨平台的组件,最好先检查一下自己的Flutter是否为最新版,如果是,再检查一下使用的Android Studio是否为最新的,如果不是,请升级!!!!!!!。
问题记录1:当真机上无法运行时,先检查开发者账号是否有问题,若无问题,将Flutter安装目录下的bin/cache目录删除,然后执行flutter doctor。
问题记录2: flutter 运行在iOS上的app,当停止运行后,app不能打开。Fuck!!!
原因似乎是由于Flutter的debug模式使用的编译方式和iOS系统有冲突。具体的解决方案就是,要么Flutter直接运行release模式,要么改Xcode的编译模式为Release模式。