Как объединить несколько провайдеров во Flutter - PullRequest
0 голосов
/ 03 августа 2020

Я новичок в разработке Flutter.

Я создаю приложение, в котором после входа пользователя в систему отображается список сообщений. Если пользователь все еще не вошел в систему, ему показывается какое-то случайное сообщение.

Я получил части приложения, различные сообщения в inte rnet. Это то, что я сделал

class TestApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider<AuthBase>(
          create: (context) => Auth(),
        ),
        StreamProvider<User>.value(
          value: Auth().onAuthStateChanged,
        ),
        ProxyProvider<User, Database>(
            update: (BuildContext context, User user, Database db) {
              return user == null
                  ? FirestoreDatabase(uid: null)
                  : FirestoreDatabase(uid: user.uid);
            }),
        ChangeNotifierProxyProvider<Database, PostProvider>(
          create: (context) => PostProvider(),
          update: (ctx, database, previousProvider) {
            print("at ChangeNotifierProxyProvider $previousProvider");
            return previousProvider.update(database);
          },
        ),
      ],
      child: MaterialApp(
        title: 'Test Project',
        home: LandingPage(),
      ),
    );
  }

Моя идея:

, если пользователь вошел в систему, StreamProvider<User>.value предоставит этому пользователю ProxyProvider<User, Database>, и он создаст базу данных с этим пользователем.

И эта база данных, в свою очередь, будет использоваться ChangeNotifierProxyProvider<Database, PostProvider> для создания провайдера, который фактически получает сообщения. Он использует базу данных для получения сообщений.

Я заметил, что даже если пользователь вошел в систему с самого начала, я получаю нулевое значение для пользователя, а затем сразу же получаю фактического пользователя.

В на целевой странице у меня есть только следующая строка, и она генерирует ошибку

final provider = Provider.of<PostProvider>(context);

Я заметил, что причиной ошибки была эта строка;

previousProvider.update(database);

Конструктор постпровайдера в первый раз и методы обновления вызываются без проблем. (здесь мы получаем нулевого пользователя) Когда FirestoreDatabase создается с фактическим пользователем, «previousProvider» имеет значение null. Это причина ошибки.

Не знаю, почему это происходит и как это исправить. Есть ли лучший способ сделать это?

Первоначально причиной может быть получение нулевого значения, даже если есть авторизованный пользователь. Как это предотвратить?

1 Ответ

0 голосов
/ 09 августа 2020

Я попытаюсь немного объяснить ваш код, чтобы мы были на одной странице

Provider<AuthBase>(
  create: (context) => Auth(), //this subscribe an Auth Class to the provider
),
StreamProvider<User>.value(
  value: Auth().onAuthStateChanged, 
  /// This subscribe a stream from another Auth Class instance
  /// Unless Auth its a singleton class, this is not related to the previous Provider
  /// and changes to Provider<AuthBase> won't affect this Stream
),

Я заметил, что даже если пользователь вошел в систему в начале, я получаю нулевое значение для user, тогда я сразу же получаю фактического пользователя.

Это происходит при использовании Stream, когда первое значение фиксируется (иногда задерживается на галочку) его null, вы можете использовать параметр initialData, если вы знаете первое значение, пока выполняется подписка на поток

Наконец

ChangeNotifierProxyProvider<Database, PostProvider>(
   create: (context) => PostProvider(),
   update: (ctx, database, previousProvider) {
     print("at ChangeNotifierProxyProvider $previousProvider");
     return previousProvider.update(database);
   },
),

update ожидает возврата значения типа PostProvider, но вы возвращаете то, что возвращает метод previousProvider.update(database) ( который, я думаю, просто обновляет какую-то внутреннюю переменную или что-то в этом роде, я считаю, что это какой-то метод void, возможно?)

Измените обновление следующим образом

update: (ctx, database, previousProvider) {
   print("at ChangeNotifierProxyProvider $previousProvider");
   return previousProvider..update(database);
   /// It's the same as writing this
   /// previousProvider..update(database);
   /// return previousProvider;
},
...