Falha no aplicativo Flutter após converter o provedor 3 para 4

8

Tentei atualizar meu aplicativo Flutter para uso Provider 4.0.1hoje e o código a seguir falhou ao atribuir um valor a nulo.

Aqui está o código que estou tentando converter. Eu mudei apenas SingleChildCloneableWidgetpara o SingleChildStatelessWidgetque compilou OK.

import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';

List<SingleChildStatelessWidget> providers = [
  ...independentServices,
  ...dependentServices,
  ...uiConsumableProviders
];

List<SingleChildStatelessWidget> independentServices = [
  Provider.value(value: Api()),
  Provider.value(value: Tbl()),
  Provider.value(value: Bill()),
  Provider.value(value: Sale()),
  Provider.value(value: Category()),
  Provider.value(value: Menu()),
];

List<SingleChildStatelessWidget> dependentServices = [
  ProxyProvider<Api, AuthenticationService>(
    update: (context, api, authenticationService) => AuthenticationService(api: api),
  ),
];

List<SingleChildStatelessWidget> uiConsumableProviders = [
  StreamProvider<User>(
    create: (context) => Provider.of<AuthenticationService>(context, listen: false).user,
  ),
    lazy: false
];

Eu implementei assim:

StreamController<User> _userController = StreamController<User>();
Stream<User> get user => _userController.stream;

A falha ocorreu nesta linha:

Future<void> _setFixedLanguageStrings(BuildContext context) async {

 User _user = Provider.of<User>(context);

 _user.homeString = await translate(context, 'Home');

O getter 'language' foi chamado em null. Receptor: nulo

Isso estava funcionando bem, Provider 3.0.3mas obviamente eu preciso fazer mais.

Meu código original veio deste tutorial .

edit: Corrigi esse problema adicionando lazy: falseno método de criação do provedor de fluxo, mas depois outro erro posteriormente neste código.

Future<String> translate(BuildContext context, _term) async {

  final String _languageCode = Provider.of<User>(context).language;

que produziu este erro:

Ocorreu uma excepção. _AssertionError ('pacote: provider / src / provider.dart': declaração com falha: linha 213 pos 7: 'context.owner.debugBuilding || listen == false || _debugIsInInheritedProviderUpdate': tentou ouvir um valor exposto com o provedor, de fora da árvore de widgets.

Provavelmente, isso é causado por um manipulador de eventos (como o botão onPressed) que chamou Provider.of sem passar listen: false.

Para corrigir, escreva: Provider.of (contexto, ouça: false);

Não é suportado porque pode reconstruir inutilmente o widget associado ao manipulador de eventos, quando a árvore do widget não se importa com o valor. )

Eu adicionei listen: falseà linha acima, que parece ter corrigido esse problema, no entanto, o próximo provedor que tentei usar produziu este erro:

Tentou ouvir um valor exposto com o provedor, de fora da árvore de widgets.

Provavelmente, isso é causado por um manipulador de eventos (como o botão onPressed) que chamou Provider.of sem passar listen: false.

Para corrigir, escreva: Provider.of (contexto, ouça: false);

Não é suportado porque pode reconstruir inutilmente o widget associado ao manipulador de eventos, quando a árvore do widget não se importa com o valor. 'package: provider / src / provider.dart': Falha na asserção: linha 213 pos 7: 'context.owner.debugBuilding || listen == false || _debugIsInInheritedProviderUpdate '

Agora devo ir para todas as instâncias em que chamo um provedor e adiciono listen: false? Preciso de alguém para explicar o que mudou e por que, como sou relativamente novo na Flutter, os documentos são escassos Provider. Muitas vezes eu chamo Provedor no meu código e esse último erro não retornou um local de código.

listen: falseAgora é sempre necessário quando não era antes ou perdi outra coisa? Estou começando a adicionar listen: false a todas as chamadas para instanciar uma variável do provedor e ela parece estar funcionando, mas essa é a abordagem correta? Devo apenas adicionar listen: falsea cada chamada Provider.ofe ligar para um dia?

O erro indica que o aplicativo tentou ouvir um valor fora da árvore do widget, mas não acho que seja esse o caso, como o chamo no método de criação do widget. Se esse erro estiver correto, de alguma forma, todos os meus provedores estão fora da árvore de widgets. O código está funcionando bem há alguns meses, os erros de escuta apareceram apenas nesta atualização.

markhorrocks
fonte
O mesmo problema ocorreu ao atualizar. A questão é: e se eu puder ou não alterar a árvore de widgets? Estou revertendo.
Dpedrinha 22/01

Respostas:

3

Eu tenho o mesmo "problema", se eu adicionar em listen: falsequalquer lugar que chamo de Provedor, o problema se foi, mas eu não sei se essa é a solução certa ...?

dukaric1991
fonte
Eu me pergunto por que listen: falsenão é o padrão para SingleChildStatelessWidget?
markhorrocks 14/01
não há erro com listen: false, mas a interface do usuário não é atualizada; portanto, é necessário algo mais para fazê-lo funcionar.
Shakle 15/01
1

listen : false chamado quando os dados não atualizam nada na interface do usuário e deve ser usado, como remover todos os cartões de um widget ao clicar no botão.

Para mais informações, leia este go_to_link

Khalil Khalil
fonte
0

listen:true sendo o padrão é lógico.

Não está especificando dentro de um manipulador de eventos que não seja lógico.listen: false

Além disso, o 4.1.0 terá uma alternativa mais curta ao Provider.of:

context.read<T>() // Provider.of<T>(context, listen: false)
context.watch<T>() // Provider.of<T>(context)
Jaime
fonte