IMO,这是解决这个问题的方法:
这是一个示例方法,我将构建一个 Flutter 应用程序,它可以读取文件并将数据写入文件以供以后使用。
这是一个可以将字符串写入 text.txt 文件的应用程序。每次启动应用程序时,它都会显示 text.txt 的内容。
我需要一个地方在磁盘上写入数据并在应用加载时再次读取它。所以我使用path_provider插件访问Documents目录(iOS上对应NSDocumentDirectory,Android上是AppData目录)。
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
创建对文件完整位置的引用(在我们的例子中是 text.txt 文件),我们使用来自 dart:io 库的 File 类。
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/text.txt');
}
需要使用 File writeAsString() 方法将字符串写入文件。它返回一个Future<File>,一旦整个操作完成,这个 File 对象就完成了。
默认情况下,writeAsString() 创建文件并在文件已存在时将其截断。
要将数据附加到现有文件,请将FileMode.append 模式作为第二个参数传递。
Future<File> writeFile(String text) async {
final file = await _localFile;
return file.writeAsString('$text\r\n', mode: FileMode.append);
}
使用 File readAsString() 方法将整个内容作为字符串读取。它返回一个Future<String>,一旦内容被读取,就会以字符串结尾。
Future<String> readFile() async {
try {
final file = await _localFile;
String content = await file.readAsString();
return content;
} catch (e) {
return '';
}
}
这是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'dart:io';
void main() {
runApp(
MaterialApp(
title: 'Read/Write Files',
home: MyApp(storage: TextStorage()),
),
);
}
class TextStorage {
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/text.txt');
}
Future<String> readFile() async {
try {
final file = await _localFile;
String content = await file.readAsString();
return content;
} catch (e) {
return '';
}
}
Future<File> writeFile(String text) async {
final file = await _localFile;
return file.writeAsString('$text\r\n', mode: FileMode.append);
}
Future<File> cleanFile() async {
final file = await _localFile;
return file.writeAsString('');
}
}
class MyApp extends StatefulWidget {
final TextStorage storage;
MyApp({Key key, @required this.storage}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
TextEditingController _textField = new TextEditingController();
String _content = '';
@override
void initState() {
super.initState();
widget.storage.readFile().then((String text) {
setState(() {
_content = text;
});
});
}
Future<File> _writeStringToTextFile(String text) async {
setState(() {
_content += text + '\r\n';
});
return widget.storage.writeFile(text);
}
Future<File> _clearContentsInTextFile() async {
setState(() {
_content = '';
});
return widget.storage.cleanFile();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Read/Write File Example'),
backgroundColor: Colors.blue,
),
body: Container(
padding: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
TextField(
controller: _textField,
),
Padding(
padding: EdgeInsets.all(20.0),
child: RaisedButton(
child: Text('Write to File'),
color: Colors.lightBlueAccent,
onPressed: () {
if (_textField.text.isNotEmpty) {
_writeStringToTextFile(_textField.text);
_textField.clear();
}
},
),
),
Padding(
padding: EdgeInsets.only(bottom: 20.0),
child: RaisedButton(
child: Text(
'Clear Contents',
style: TextStyle(color: Colors.white),
),
color: Colors.grey,
onPressed: () {
_clearContentsInTextFile();
},
),
),
Expanded(
flex: 1,
child: new SingleChildScrollView(
child: Text(
'$_content',
style: TextStyle(
color: Colors.blue,
fontSize: 22.0,
),
),
),
),
],
),
),
);
}
}
这是运行时的样子:
你可以根据你的要求来玩。
还有关于如何在 Flutter webview 中加载 html 文件的其他问题,这是我的方法:
您实际上可以使用webview_flutter 插件使其工作。
在你的 Flutter 应用的根目录下创建一个 assets 文件夹,然后将你的 .html 文件放到 assets 文件夹中。
您应该将您的 .html 文件添加到 pubspec.yaml 文件中的 assets 下。
pubspec.yaml
assets:
- assets/SampleHtml.html
这是从本地文件加载 html 的示例实现:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
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: 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> {
Future<String> localLoader() async {
return await rootBundle.loadString('assets/SampleHtml.html');
}
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
future: localLoader(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return WebView(
initialUrl:
new Uri.dataFromString(snapshot.data, mimeType: 'text/html')
.toString(),
javascriptMode: JavascriptMode.unrestricted,
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
});
}
}
SampleHtml.html
<!DOCTYPE html>
<meta charset="utf-8">
<title>Sample HTML</title>
<html>
<head>
<link rel="stylesheet">
</head>
<body>
<h1>Flutter Webview</h1>
<p>A Flutter plugin that provides a WebView widget.</p>
<ul>
<li>List 1</li>
<li>List 2</li>
<li>List 3</li>
</ul>
</body>
</html>
看起来是这样的: