我是 Flutter 的新手。当我尝试将数据上传到服务器时,我遇到了一些问题,例如: 1.NoSuchMethodError: getter 'friendsList' 在 null 上被调用 2.DioError [DioErrorType.DEFAULT]:将对象转换为可编码对象失败:“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() 类中使用的添加按钮
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;
},
);
}
}
答案 0 :(得分:0)
FormData
实例,如果它被另一个对象包装或者如果您使用嵌套的 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"
},
});
或类似的东西,但你不能用另一个对象包装 FormData
。请参阅此issue
如果上面的肯定是对的,就没有必要使用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;
},
);
}
答案 1 :(得分:0)
问题出在这里:
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
变量分配任何值。所以,它是空的。我不知道它究竟来自哪里。但是需要给它赋值。
此外,据我所知,您正在尝试访问另一个小部件中的变量。这可以通过将数据传递给下一个 Widget 来完成,如下所示: 你正在做的是传递错误的数据。我建议你通过这个而不是传递索引。
class FriendTextFields extends StatefulWidget {
final String friend;
FriendTextFields(this.friend);
final GlobalKey<_FriendTextFieldsState> serviceKey = new GlobalKey();
@override
_FriendTextFieldsState createState() => _FriendTextFieldsState();
}
但是,我非常建议您使用 Provider 来访问这些东西。它会帮助你很多。通过 here 检查提供程序文档。您可以通过 here 了解有关 Provider 的更多信息。