できるだけ多くのコードを提供しようとします。(主に画像に関しては、画像以外に不要なコードを投稿する代わりに「他のデータ」を使用することをお勧めします)
私のアプリにはFile image;
プロバイダーがあり、アプリに表示するのに問題があります。File
画像パスを渡すことができず、firebase からデータを取得firebase
しようとするとアプリがクラッシュします。Fetching
できるだけ多くのコードを提供しようとします。
これが私のプロバイダーです:
import 'dart:io';
class AddCar {
// other data
File image;
AddCar({
// other data
this.image,
});
}
これが私のプロバイダーコードです:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:io';
import '../add_ons/add_car.dart';
List<AddCar> _cars = [];
class Cars with ChangeNotifier {
List<AddCar> get cars {
return [..._cars];
}
Future<void> fetchAndSetCars() async {
const url = 'https://mycustomlink.firebaseio.com/cars.json';
try {
final response = await http.get(url);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
var loadedCars = extractedData
.map<String, AddCar>((carId, carData) => MapEntry(
carId,
AddCar(
// other data
image: File(carData['image']),
)))
.values
.toList();
_cars = loadedCars;
print(extractedData);
print(loadedCars);
notifyListeners();
} catch (error) {
throw (error);
}
}
AddCar findById(String id) {
return _cars.firstWhere((carProd) => carProd.id == id);
}
void addCar(AddCar car) {
const url = 'https://mycustomlink.firebaseio.com/cars.json';
http.post(
url,
body: json.encode({
// other data
'image': car.image.toString(),
}),
);
final newCar = AddCar(
// other data
image: car.image,
);
_cars.insert(0, newCar);
notifyListeners();
}
}
form
ユーザーが表示するデータを入力する場所は次のとおりです。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_app/app_localization.dart';
import 'package:google_fonts_arabic/fonts.dart';
import 'package:provider/provider.dart';
import 'package:file_picker/file_picker.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' as syspaths;
import '../add_ons/add_car.dart';
import '../providers/car_provider.dart';
import '../drawer/drawer.dart';
import '../screens/cars_screen.dart';
import '../app_localization.dart';
class CreateCar extends StatefulWidget {
static const routeName = '/create-car';
@override
_CreateCarState createState() => _CreateCarState();
}
class _CreateCarState extends State<CreateCar> {
final _name = TextEditingController();
final _price = TextEditingController();
final _address = TextEditingController();
String img;
static Future<String> fileToB64(File f) async {
List<int> imageBytes = f.readAsBytesSync();
return base64Encode(
imageBytes,
);
}
Future<void> _takePicture() async {
final imageFile = await ImagePicker.pickImage(
source: ImageSource.gallery,
);
fileToB64(data.image).then((d) {
setState(() {
img = d; //base64Decode(d);
});
});
}
final _form = GlobalKey<FormState>();
int currStep = 0;
static AddCar data = new AddCar(
id: null,
date: DateTime.now(),
sponsNum: '',
);
void _saveForm() {
final isValid = _form.currentState.validate();
if (!isValid) {
return;
}
_form.currentState.save();
Provider.of<Cars>(context, listen: false).addCar(data);
Navigator.of(context).pushNamed(CarsScreen.routeName);
print('this works');
}
@override
Widget build(BuildContext context) {
List<Step> steps = [
Step(
title: Text(
AppLocalizations.of(context).createTabTitle,
),
isActive: true,
state: StepState.indexed,
content: Column(
children: <Widget>[
// other data
],
),
),
Step(
title: Text(
AppLocalizations.of(context).createCarDetails,
),
isActive: true,
state: StepState.indexed,
content: Column(
children: <Widget>[
// other data
Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 25.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Theme.of(context).primaryColor),
borderRadius: BorderRadius.circular(50.0),
),
child: FlatButton(
child: Text(AppLocalizations.of(context).createAddImages),
onPressed: _takePicture,
),
),
)
],
)
],
),
),
];
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
AppLocalizations.of(context).createCarPageTitle,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: ArabicFonts.Tajawal,
package: 'google_fonts_arabic',
),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(Icons.save),
onPressed: _saveForm,
),
IconButton(
icon: Icon(Icons.arrow_forward),
onPressed: () {
Navigator.of(context).pop();
},
)
],
),
],
),
drawer: MyDrawer(),
body: Row(
children: <Widget>[
Form(
key: _form,
child: Expanded(
child: Stepper(
steps: steps,
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
// currStep = 0;
}
});
},
onStepCancel: () {
setState(() {
if (this.currStep > 0) {
this.currStep = this.currStep - 1;
} else {
this.currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
),
),
],
),
);
}
}
これは、後でコードを表示する「CarItem」に渡されます。
import 'package:flutter/material.dart';
import 'package:google_fonts_arabic/fonts.dart';
import '../icons/MyIcons.dart';
import 'dart:io';
import '../details/car_details.dart';
import '../app_localization.dart';
class CarItem extends StatelessWidget {
final File image;
CarItem(
this.image,
);
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Theme.of(context).primaryColor, width: 2.0),
),
),
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Color.fromARGB(255, 245, 245, 245),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(17.0, 4.0, 17.0, 4.0),
child: Row(
textDirection: TextDirection.rtl,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
// other data
],
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width * 0.35,
height: MediaQuery.of(context).size.width * 0.35,
child: GestureDetector(
child: Image.file(
image,
fit: BoxFit.fill,
),
onTap: () {
Navigator.of(context).pushNamed(
MyCarDetails.routeName,
arguments: id,
);
},
),
),
Container(
width: MediaQuery.of(context).size.width * 0.65,
margin: EdgeInsets.all(0),
padding: const EdgeInsets.fromLTRB(22.0, 5.0, 22.0, 0),
child: Column(
children: <Widget>[
// other data
],
),
),
],
),
),
],
),
],
),
);
}
}
このコードは、コードを呼び出してアプリに表示するリストによって呼び出されます。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:google_fonts_arabic/fonts.dart';
import '../providers/car_provider.dart';
import '../widget/car_item.dart';
class CarsList extends StatefulWidget {
@override
_CarsListState createState() => _CarsListState();
}
class _CarsListState extends State<CarsList> {
@override
Widget build(BuildContext context) {
final carsData = Provider.of<Cars>(context);
final car = carsData.cars;
return car.isEmpty
? Center(
child: Text(
'no data yet available',
style: TextStyle(
fontFamily: ArabicFonts.Tajawal,
fontWeight: FontWeight.bold,
package: 'google_fonts_arabic',
),
))
: ListView.builder(
padding: const EdgeInsets.only(bottom: 47.0),
itemCount: car.length,
itemBuilder: (ctx, i) => CarItem(
// other data
car[i].image,
),
);
}
}
これは、取得したデータを表示しようとしたときに発生し続けるエラーです。
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building CarItem(dirty, dependencies: [_LocalizationsScope-[GlobalKey#31697], MediaQuery, _InheritedTheme]):
The method '+' was called on null.
Receiver: null
Tried calling: +("25")
User-created ancestor of the error-causing widget was
ListView
lib\home_parts\cars_area.dart:49
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1 CarItem.build
package:flutter_app/widget/car_item.dart:151
#2 StatelessElement.build
package:flutter/…/widgets/framework.dart:4009
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:3941
#4 Element.rebuild
package:flutter/…/widgets/framework.dart:3738
...
════════════════════════════════════════════════════════════════════════════════
どうすればこれを修正できますか? データをfirebaseに渡してアプリに表示する方法に問題がありますか?