一、获取Android的文件路径
使用PathProvider插件获取文件路径,需要再pubspec.yaml添加依赖;添加后执行命令 “flutter packages get”,成功后即可使用。
path_provider: ^0.4.1
PathProvider 插件获取文件路径有3钟:
1、getTemporaryDirectory:此方法获取临时目录,Android上对应getCacheDir()目录,即data/data/packageName/cache。
2、getApplicationDocumentsDirectory:此方法获取应用程序的文档目录,Android上对应/data/data/packageName/app_flutter目录
3、getExternalStorageDircetory:此方法获取外部存储目录,Android上对应getExternalStorageDirectory目录,即外部分出目录根目录。
注意:Android系统操作sd卡文件需要读写权限。在AndroidManifest.xml中添加读写权限。
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
二、文件夹常用操作
1、创建目录:
var rootDir = await getTemporaryDirectory();
Directory('$rootDir${Platform.pathSeparator}dir1').create();
create中有一个可选参数recursive,默认值为false,false表示只能创建最后一级文件夹,如果创建“dir1/dir2”这种嵌套文件夹,recursive为false时将抛出异常,而设置为true可以创建嵌套文件夹。例如,在根目录创建“dir1/dir2”文件夹,如下:
var rootDir = await getTemporaryDirectory();
var dir2 = await
Directory('$rootDir${Platform.pathSeparator}dir1${Platform.pathSeparator}dir2${Platform.pathSeparator}').create(recursive: true);
2、重命名目录
var dir3 = await dir2.rename('${dir2.parent.absolute.path}/dir3');
3、删除目录
await dir3.delete();
await dir2.delete(recursive: true);
recurise设置为true,删除当前文件夹及文件夹下所有内容。
4、遍历目录下文件
Stream<FileSystemEntity> fileList = rootDir.list(recursive: false) ;
await for (FileSystemEntity entity in fileList) {
print(entity.path);
}
recursive默认为false,表示只遍历当前目录;设置为true,表示遍历当前目录及子目录。
三、文件常用操作
1、创建文件
var rootDir = await getTemporaryDirectory();
var filetest = await File('$rootDir/dir1/file.txt').create(recursive: true);
2、写入文件
//字符串写入文件
filetest.writeAsString("Flutter 实践入门");
//将byte写入文件
filetest.writeAsBytes(Utf8Encoder().convert("Flutter 实践入门"));
//向文件末尾追加内容
filetest.openWrite(mode: FileMode.append).write("Flutter 实践入门\n");
3、读取文件
//读取一行内容
List<String> lines = await filetest.readAsLines();
4、删除文件
filetest.delete();
四、HTTPClient网络请求(不常用)
HTTP网络请求方式包含GET、 POST、 HEAD 、PUT 、DELETE、 TRACE 、CONNECT 、OPTIONSD等。本节介绍dart:io。
发起一个HTTP请求需要如下5个步骤:
1、创建HttpClient。
var httpClient = new HttpClient();
2、构建Uri.
var uri = Uri(scheme: 'http',host: 'www.baidu.com',queryParameters: {
'params1:':'',
'params2:':'',
});
3、打开HTTP连接
HttpClientRequest request = await httpClient.getUrl(uri);
4、设置header
需要通过HttpClientRequest设置header
HttpClientRequest request = await httpClient.getUrl(uri);
request.headers.add('','');
5、发送请求并接续返回的数据。
ttpClientResponse response = await request.close();
String responseBody = await response.transform(utf8.decoder).join();
五、dio 网络请求(常用)
使用dio需要添加依赖,在pubspec.yaml中添加,用flutter packages get命令获取:
dio: ^3.0.7
建议将dio设置为单例,这样可以对所有的HTTP请求进行同意配置,比如超时设置、公共header、cookie等。设置统一参数方法:
var options = BaseOptions(
baseUrl: '_host',
connectTimeout: 5000,
receiveTimeout: 3000,
);
Dio _dio = Dio(options);
1、发起请求
(1)发起get请求
Response response = await _dio.get("/test ? id = 12&name = flutter");
print(response.data.toString());
(2)发起post请求
Response response = await _dio.post("/test",data: {"id":12,"name":"flutter"});
print(response.data.toString());
(3)发起多个并发请求
List<Response> response = await Future.wait([_dio.post("/info"),_dio.get("/token")]);
2、下载文件
await _dio.download(urlPath, savePath,onReceiveProgress: (count,total) {
//下载进度回调
});
3、发送FormData
FormData formData = FormData.fromMap({
"name":"flutter",
"age":25,
});
Response response = await _dio.post("/info",data: formData);
4、通过FormData上传多个文件
FormData formData = FormData.fromMap({
"name":"flutter",
"age":25,
"file":await MultipartFile.fromFile("./text.txt",filename: "upload.txt"),
"files":[
await MultipartFile.fromFile("./text1.txt",filename: "upload1.txt"),
await MultipartFile.fromFile("./text2.txt",filename: "upload2.txt"),
],
});
Response response = await _dio.post("/info",data: formData);
5、监听发送(上传)数据进度
Response response = await _dio.post("/info",data: formData,onSendProgress: (int send,int total){
print("$send,$total");
});
六、json数据转Model
老孟《flutter入门实践》148页,需要的时候再学习。
七、项目实践:记事本
完整程序可以运行
import 'dart:convert';
import 'dart:io';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: NodeDemo(),
);
}
}
class NodeDemo extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _NodeDemo();
throw UnimplementedError();
}
}
class NoteInfo {
const NoteInfo(this.name, this.path,this.updateTime);
final String name;
final String path;
final DateTime updateTime;
}
String getFileNameFromPath(String path){
int index = path.lastIndexOf('/');
if (index <= 0) {
return path;
}
return path.substring(index + 1);
}
class _NodeDemo extends State<NodeDemo> {
@override
void initState() {
_loadNote();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _noteList.length == 0 ? _buildEmpty() : _buildList(),
floatingActionButton: RaisedButton(
padding: EdgeInsets.all(10),
child: Icon(
Icons.mode_edit,
color: Theme.of(context).primaryColor,
size: 35,
),
shape: CircleBorder(),
onPressed: () async {
var result = await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return NoteEdit("");
}));
_loadNote();
},
),
);
throw UnimplementedError();
}
//构建日记列表
_buildList() {
return ListView.separated(
itemBuilder: (context,index) {
return InkWell(
onTap: () async {
var result = await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return NoteEdit(_noteList[index].path);
}));
_loadNote();
},
child: Container(
child: ListTile(
title: Text('${_noteList[index].name}'),
subtitle: Text('${_noteList[index].updateTime}'),
),
),
);
},
separatorBuilder: (context,index) {
return Divider(
height: 1,
);
},
itemCount: _noteList.length);
}
List<NoteInfo> _noteList = [];
//遍历已经存在的日记
_loadNote() async {
//遍历日记目录下所有文件
getTemporaryDirectory().then((dir) async {
List<FileSystemEntity> dirs = dir.listSync(recursive: false);
List<FileSystemEntity> files = [];
for (var dir in dirs) {
if ((await dir.stat()).type == FileSystemEntityType.file) {
files.add(dir);
}
}
//排序
files.sort((f1, f2) {
try {
var dt1 = File(f1.path).lastModifiedSync();
var dt2 = File(f2.path).lastModifiedSync();
return dt2.millisecondsSinceEpoch - dt1.millisecondsSinceEpoch;
} catch (e) {
print(e);
return 0;
}
});
_noteList.clear();
//将文件转换为日记信息
files.forEach((f) {
var file = File(f.path);
if (file.path.endsWith('txt')) {
_noteList.add(NoteInfo(getFileNameFromPath(file.path), file.path,
file.lastModifiedSync()));
}
});
setState(() {
});
});
}
//构建没有写日志的界面
_buildEmpty(){
return Center(
child: Text('空空如也,快去写日志吧!',style: TextStyle(color: Colors.black.withOpacity(0.6),),),
);
}
}
class NoteEdit extends StatefulWidget {
String path;
NoteEdit(String path) {
this.path = path;
}
@override
State<StatefulWidget> createState() {
return _NoteEdit();
throw UnimplementedError();
}
}
class _NoteEdit extends State<NoteEdit> {
TextEditingController _titleController;
TextEditingController _contentController;
@override
void initState() {
_titleController = TextEditingController();
_contentController = TextEditingController();
_loadData();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: const Icon(Icons.done),
tooltip: 'Show Snackbar',
onPressed: () {
_save();
},
),
],
),
body: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: <Widget>[
TextField(
controller: _titleController,
decoration: InputDecoration(hintText: '输入日记名称'),
),
Expanded(
child: TextField(
controller: _contentController,
decoration: InputDecoration(
hintText: '开始你的故事'
),
maxLines: 2000,
),
),
],
),
),
),
);
throw UnimplementedError();
}
_loadData() async{
if (widget.path != null) {
var fileName = getFileNameFromPath(widget.path);
print("lilili len = ${fileName.length}" );
if (fileName.length != 0) {
fileName = fileName.substring(0,fileName.length - 4);
_titleController.text = fileName;
var content = Utf8Decoder().convert(await File(widget.path).readAsBytes());
_contentController.text = content;
}
setState(() {
});
}
}
//保存
_save() async {
try{
var title = _titleController.text;
var content = _contentController.text;
var rootDir = await getTemporaryDirectory();
print("rootdir = ${rootDir}");
var file = File('${rootDir.path}/$title.txt');
var exits = file.existsSync();
if (!exits) {
//不存在
file.createSync(recursive: true);
}
file.writeAsStringSync(content);
Navigator.of(context).pop(title);
}catch(e) {
print(e);
}
}
}