как передать базу данных в качестве аргумента конструктора классу ...... и использовать его как переменную экземпляра, а не с Provider.of <Database> - PullRequest
0 голосов
/ 21 марта 2020

Я хочу записать данные в базу данных пожарного хранилища.

Я написал код в классе подписок следующим образом:

import 'package:flutter/material.dart';
import 'package:flutterapptest/services/database.dart';
import 'package:provider/provider.dart';

class Subscriptions extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Subscribed'),
        ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => _addTrack(context),
      ),
    );
  }
  Future<void> _addTrack(BuildContext context) async {
    final database = Provider.of<Database>(context, listen: false);
    await database.addTrack({
      'name': 'Track',
      'time': 20,
    });
  }
}

в классе базы данных ......

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:meta/meta.dart';

abstract class Database {
Future<void> addTrack(Map<String, dynamic> trackData);
}
class FirestoreDatabase implements Database {
  FirestoreDatabase({@required this.uid}) : assert(uid != null);
  final String uid;

  Future<void> addTrack(Map<String, dynamic> trackData) async{
    final path = '/users/$uid/track/track_abc';
    final documentReference = Firestore.instance.document(path);
    await documentReference.setData(trackData);
  }
}

для этого я получаю ошибку:

не удалось найти правильный Provider<Database> над виджетом подписок

Для этого друг предложил мне сделать:

Если вы используете sh виджет Subscriptions внутри маршрута, у него не будет доступа к Provider.of<Database>.

Самое быстрое решение - передать Database в качестве конструктора. аргумент класса Subscriptions и использовать его в качестве переменной экземпляра, а не с Provider.of<Database>

Может кто-нибудь помочь мне, что мне теперь делать? Я новичок, чтобы трепетать.

1 Ответ

0 голосов
/ 24 марта 2020

Вот как бы я это сделал. Я знаю, что это включает в себя гораздо больше, чем просто функцию addTrack, но я думаю, что вам также когда-нибудь понадобится глобальное состояние и changeNotifier, иначе нет смысла использовать провайдера.

Сначала создайте службу:

import 'package:cloud_firestore/cloud_firestore.dart';

final CollectionReference firestoreUsers =
    Firestore.instance.collection('users');

class UserService {
  static Future<Stream<Map<String, dynamic>>> streamTrack(String userId) async {
    Stream<DocumentSnapshot> query =
        await firestoreUsers.document('pathToListen...').snapshots();
    return query.map((doc) => Map.from(doc.data));
  }

  static addTrack(String userId, Map<String, dynamic> trackData) async {
    await firestoreUsers
        .document(userId)
        .collection('track')
        .document('track_abc')
        .setData(trackData);
  }
}

Затем провайдер, который содержит глобальное состояние и использует changeNotifier. Это просто заполнители. Поместите туда все, что вы хотите прослушать в базе данных.

import 'dart:async';
import 'package:flutter/material.dart';
import '../models_services/user_services.dart';

class UserProvider with ChangeNotifier {

  // your global state, if you want to listen for data from database
  StreamSubscription<Map<String, dynamic>> trackStream;
  Map<String, dynamic> _streamedTrack;
  Map<String, dynamic> get streamedTrack => _streamedTrack;

  Future streamCurrentTrack(uid) async {

    if(trackStream != null) {
      trackStream.cancel();
    }
    Stream<Map<String, dynamic>> res = await UserService.streamTrack(uid);

    trackStream = res.listen((track) {
      _streamedTrack = track;
      notifyListeners();
    });
  }

  Future<void> addTrack(Map<String, dynamic> trackData) async {
    // not sure what this is doing, i guess uid is null here...
    FirestoreDatabase({@required this.uid}) : assert(uid != null);
    final String uid;

    await UserService.addTrack(uid, trackData);
  }
}

Используйте провайдера с changeNotifier в вашем коде:

import 'package:flutter/material.dart';
import 'package:flutterapptest/provider/user_provider.dart';
import 'package:provider/provider.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [
          ChangeNotifierProvider(create: (context) => UserProvider()),
          ...
        ],
        child: MaterialApp(
            home: Scaffold(body: Subscriptions()
                )));
  }
}

class Subscriptions extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Subscribed'),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => _addTrack(context),
      ),
    );
  }

  Future<void> _addTrack(BuildContext context) async {
    final database = Provider.of<UserProvider>(context, listen: false);
    await database.addTrack({
      'name': 'Track',
      'time': 20,
    });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...