0

できるだけ多くのコードを提供しようとします。(主に画像に関しては、画像以外に不要なコードを投稿する代わりに「他のデータ」を使用することをお勧めします)

私のアプリには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に渡してアプリに表示する方法に問題がありますか?

4

0 に答える 0