![](/img/trans.png)
[英]DioError [DioErrorType.DEFAULT]: Converting object to an encodable object failed: Instance of 'FormData' in Flutter
[英]DioError [DioErrorType.DEFAULT]: Converting object to an encodable object failed: Instance of 'FormData'
我是 Flutter 的新手。当我尝试将数据上传到服务器时,我遇到了一些问题,例如: 1.NoSuchMethodError:在 null 上调用了 getter 'friendsList' 2.DioError [DioErrorType.DEFAULT]:将 object 转换为可编码的 object失败:“FormData”的实例
import 'dart:convert';
import 'dart:io';
import 'package:data_collection/helperClass/testForAddButton.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http_parser/http_parser.dart';
class AutoCompleteDemo extends StatefulWidget {
@override
_AutoCompleteDemoState createState() => _AutoCompleteDemoState();
}
class _AutoCompleteDemoState extends State<AutoCompleteDemo> {
final hospitalNameEng = TextEditingController();
final _serviceKey = GlobalKey<FormState>();
static List<String> friendsList = [];
File imageFile;
String servicejson;
bool loading = true;
@override
void initState() {
super.initState();
}
//for camera dialogBox
Future<void> _showChoiceDialog(BuildContext context) {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Make a Choice"),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
GestureDetector(
child: Text("Gallery"),
onTap: () {
_openGallery(context);
},
),
Padding(padding: EdgeInsets.all(5.0)),
GestureDetector(
child: Text("Camera"),
onTap: () {
_openCamera(context);
},
)
],
),
),
);
});
}
//for image
Widget _decideImageView() {
if (imageFile == null) {
return Text("No Image Selected");
} else {
Image.file(
imageFile,
width: 400,
height: 400,
);
}
return Image.file(
imageFile,
width: 400,
height: 400,
);
}
//Dio part
Dio dio = new Dio();
Future postData() async {
final String apiUrl = "MY_API";
setState(() {
servicejson = jsonEncode(friendsList);
});
String imageFileName = imageFile.path.split('/').last;
FormData formData = new FormData.fromMap({
"image": await MultipartFile.fromFile(imageFile.path,
filename: imageFileName, contentType: new MediaType('image', 'png')),
"type": "image/png"
});
dynamic allOfTheUploadData = {
"name": hospitalNameEng,
"Services": servicejson,
"Image": formData,
};
var response = await dio.post(apiUrl,
data: allOfTheUploadData,
options: Options(headers: {
"accept": "*/*",
"Authorization": "Bearer accresstoken",
"Content-type": "multipart/form-data",
}));
return response.data;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
//margin: const EdgeInsets.only(bottom:5.0),
child: TextField(
controller: hospitalNameEng,
decoration:
InputDecoration(hintText: 'Hospital Name In English'),
),
padding: EdgeInsets.all(10.0),
),
//service
Container(
child: Form(
key: _serviceKey,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Services',
style: TextStyle(
fontWeight: FontWeight.w700, fontSize: 16),
),
..._getServices(),
SizedBox(
height: 20,
),
],
),
),
),
),
//camera
Container(
child: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
_showChoiceDialog(context);
},
child: Text("Select Image"),
),
_decideImageView(),
],
),
),
),
//send to server
Container(
child: Center(
child: Column(
children: <Widget>[
FlatButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: BorderSide(color: Colors.green)),
onPressed: () async {
try {
await postData().then((value) {
print(value);
});
} catch (e) {
print(e);
}
},
child: Text("Submit"),
),
],
),
),
),
],
),
),
);
}
//services
List<Widget> _getServices() {
List<Widget> friendsTextFieldsList = [];
for (int i = 0; i < friendsList.length; i++) {
friendsTextFieldsList.add(Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Row(
children: [
Expanded(child: FriendTextFields(i)),
SizedBox(
width: 16,
),
// we need add button at last friends row only
_addRemoveButton(i == friendsList.length - 1, i),
],
),
));
}
return friendsTextFieldsList;
}
Widget _addRemoveButton(bool add, int index) {
return InkWell(
onTap: () {
if (add) {
// add new text-fields at the top of all friends textfields
friendsList.insert(0, null);
} else
friendsList.removeAt(index);
setState(() {});
},
child: Container(
width: 30,
height: 30,
decoration: BoxDecoration(
color: (add) ? Colors.green : Colors.red,
borderRadius: BorderRadius.circular(20),
),
child: Icon(
(add) ? Icons.add : Icons.remove,
color: Colors.white,
),
),
);
}
//gallery
_openGallery(BuildContext context) async {
var picture = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
imageFile = picture;
});
Navigator.of(context).pop();
}
//Camera
_openCamera(BuildContext context) async {
var picture = await ImagePicker.pickImage(source: ImageSource.camera);
setState(() {
imageFile = picture;
});
Navigator.of(context).pop();
}
}
对于我在 Widget _getservices() 中使用的添加按钮 class
import 'package:autocomplete_textfield/autocomplete_textfield.dart';
import 'package:flutter/material.dart';
import '../players.dart';
class FriendTextFields extends StatefulWidget {
final int index;
FriendTextFields(this.index);
final GlobalKey<_FriendTextFieldsState> serviceKey = new GlobalKey();
@override
_FriendTextFieldsState createState() => _FriendTextFieldsState();
}
class _FriendTextFieldsState extends State<FriendTextFields> {
GlobalKey<AutoCompleteTextFieldState<Division>> key = new GlobalKey();
TextEditingController _serviceController;
AutoCompleteTextField searchTextField;
void _loadData() async {
await PlayersViewModel.loadPlayers();
}
@override
void initState() {
_loadData();
super.initState();
_serviceController = TextEditingController();
}
@override
void dispose() {
_serviceController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// ignore: non_constant_identifier_names
var _AutoCompleteDemoState;
_serviceController.text = _AutoCompleteDemoState.friendsList[widget.index] ?? '';
});
var _AutoCompleteDemoState;
return TextFormField(
controller:
_serviceController, // save text field data in friends list at index
// whenever text field value changes
onChanged: (v) => _AutoCompleteDemoState.friendsList[widget.index] = v,
decoration: InputDecoration(hintText: 'Add a unique code: Service Name\''),
validator: (v) {
if (v.trim().isEmpty) return 'Please enter something';
return null;
},
);
}
}
FormData
,则 Dio 无法解析FormData
实例,因此不要这样做:FormData formData = new FormData.fromMap({
"image": await MultipartFile.fromFile(imageFile.path,
filename: imageFileName, contentType: new MediaType('image', 'png')),
"type": "image/png"
});
dynamic allOfTheUploadData = {
"name": hospitalNameEng,
"Services": servicejson,
"Image": formData,
};
做这个:
FormData formData = new FormData.fromMap({
"name": hospitalNameEng,
"Services": servicejson,
"Image": {
"image": await MultipartFile.fromFile(imageFile.path,
filename: imageFileName, contentType: new MediaType('image', 'png')),
"type": "image/png"
},
});
或类似的东西,但你不能用另一个 object 包装FormData
。 参考这个问题
如果上面的肯定是对的,就不需要使用Provider了,可以把friendsList
和当前索引传给FriendTextFields
: FriendTextFields(i, friendsList)
。 在第二个文件中:
class FriendTextFields extends StatefulWidget {
final int index;
final List<String> friendsList;
FriendTextFields(this.index, this.friendsList);
final GlobalKey<_FriendTextFieldsState> serviceKey = new GlobalKey();
@override
_FriendTextFieldsState createState() => _FriendTextFieldsState();
}
和
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
_serviceController.text = widget.friendsList[widget.index] ?? '';
});
return TextFormField(
controller:
_serviceController, // save text field data in friends list at index
// whenever text field value changes
onChanged: (v) => widget.friendsList[widget.index] = v,
decoration: InputDecoration(hintText: 'Add a unique code: Service Name\''),
validator: (v) {
if (v.trim().isEmpty) return 'Please enter something';
return null;
},
);
}
问题出在这里:
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// Here:
var _AutoCompleteDemoState;
_serviceController.text = _AutoCompleteDemoState.friendsList[widget.index] ?? '';
});
var _AutoCompleteDemoState;
return TextFormField(
controller:
_serviceController, // save text field data in friends list at index
// whenever text field value changes
onChanged: (v) => _AutoCompleteDemoState.friendsList[widget.index] = v,
decoration: InputDecoration(hintText: 'Add a unique code: Service Name\''),
validator: (v) {
if (v.trim().isEmpty) return 'Please enter something';
return null;
},
);
}
在这里,您没有为_AutoCompleteDemoState
变量分配任何值。 所以,它是 null。 我不知道它究竟是从哪里来的。 但它需要被赋予一些价值。
另外,据我了解,您正在尝试访问另一个小部件中的变量。 这可以通过将数据传递给下一个小部件来完成,如下所示:您所做的是传递了错误的数据。 我建议您不要传递索引,而是传递这个。
class FriendTextFields extends StatefulWidget {
final String friend;
FriendTextFields(this.friend);
final GlobalKey<_FriendTextFieldsState> serviceKey = new GlobalKey();
@override
_FriendTextFieldsState createState() => _FriendTextFieldsState();
}
但是,我非常建议您使用 Provider 来访问这些东西。 这会对你有很大帮助。 在此处查看 Provider 文档。 您可以在此处了解有关 Provider 的更多信息。
由于日志记录拦截器出现了同样的错误,它试图对我的 FormData 进行 json.encode。
工作代码只是:
var file = File(path);
var fileName = file.path.split('/').last;
FormData formData = FormData.fromMap({
"file": await MultipartFile.fromFile(file.path, filename: fileName),
});
Response resp = await dio.post(endpoint, data: formData);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.