Flutter:我的notifyListeners()不起作用,但只在发布版apk中起作用

isr3a4wc  于 2023-02-05  发布在  Flutter
关注(0)|答案(2)|浏览(252)

我有一个页面,显示加载,而使我的API调用,一旦调用完成,它显示接收到的数据。
在调试器一切正常工作,但当我创建的apk与'flutter build apk',并下载它,加载仍然无限期.
我还在进行API调用的Provider函数的末尾放置了一个showDialog(我将此showDialog放在notifyListeners()的正下方)。
我不明白为什么在调试时它能工作,而在发布时它不能。
(This notifyListeners不起作用只是对我进行的每个API调用都起作用)
以下是进行API调用的提供程序函数的代码:

Future<void> getUserSites(context) async {
     _userSites.clear();
     isLoading = true;
     notifyListeners(); 
     try { 
       final response = await NetworkService.call( 
           url: '/api/structure/Sites', 
           method: Method.Get, 
           context: context) as List<dynamic>;      
     for (var i = 0; i < response.length; i++) {
        _userSites.add(Sites.fromJson(response.elementAt(i)));
      }

      if (defaultSite == null) {
        if (SimplePreferences.getDefaultSite() == null) {
          defaultSite = _userSites.isNotEmpty ? _userSites.first : null;
          if (defaultSite != null) {
            SimplePreferences.setDefaultSite(defaultSite!.id);
          }
        } else {
          defaultSite = _userSites.firstWhere(
              (element) => element.id == SimplePreferences.getDefaultSite()!);
        }
      }

  
    } catch (e) {
      inspect(e);
      if (SimplePreferences.getToken() != null) {
        showDialog(
          context: context,
          builder: (ctx) => AlertDialog(
            title: const Text('General Error'),
            content: Text(e.toString()),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text(
                  'Ok',
                ),
              )
            ],
          ),
        );
      }
      // throw e;
    }
    isLoading = false;
    notifyListeners();
    showDialog(
          context: context,
          builder: (ctx) => AlertDialog(
            title: const Text('getUserSites done!'),
            content: Text(_userSites.toString()),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text(
                  'Ok',
                ),
              )
            ],
          ),
        );
  }

此为首页代码:

class HomePageScreen extends StatelessWidget { const HomePageScreen({super.key}); static const String routeName = '/';

@override Widget build(BuildContext context) { log('New Page: Home Page'); final provider = Provider.of<MyManager>(context);
return provider.isLoading ? const Center(
        child: CircularProgressIndicator(),
      )
    : SingleChildScrollView(
        physics: const BouncingScrollPhysics(),
        child: Container(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              MainButton(
                onTap: () async {
                    Navigator.of(context)
                      .pushNamed(ShowPatrolScreen.routeName);
                      await provider.getPatrol(context);
                },
                icon: Icons.home,
                title: 'ShowPatrol',
              ),
              printSito(provider.defaultSite?.description ?? 'Nessun Sito', context),
              PrintRequestZ(
                showCompleted: false,
              ),
            ],
          ),
        ),
      );
}

Widget printSito(String name, context) { .... //pass context for Navigator and Theme } } `

这是主页面

...
final myScreens = [
     const HomePageScreen(),
     ...
];

@override
void initState() {
    // TODO: implement initState
    super.initState();
    print('token: ${SimplePreferences.getToken()}');
    if (SimplePreferences.getToken() == null){
       Navigator.of(context).pushReplacementNamed('/Auth');
    }
    var provider = Provider.of<MyManager>(context, listen: false);
    provider.setAll(context); //this function calls all my API calls, but for testing, I commented out all other functions and kept only the one written above
}

@override
Widget build(BuildContext context) {
    var provider = Provider.of<MyManager>(context);
    return Scaffold(
      appBar: const MyAppBar(title: 'Ronda',canGoBack: false,),
      body: myScreens[currentPage],
      bottomNavigationBar: ...
    ),
}

先谢了!

w1jd8yoj

w1jd8yoj1#

经过一番研究,我找到了解决方案。你必须在父组件中使用WidgetsBinding.instance.addPostFrameCallback。所以我的主页现在看起来像这样:

@override
    void initState() {
        // TODO: implement initState
        super.initState();
        print('token: ${SimplePreferences.getToken()}');
        if (SimplePreferences.getToken() == null){
           Navigator.of(context).pushReplacementNamed('/Auth');
        }
        WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
           var provider = Provider.of<MyManager>(context, listen: false);
           provider.setAll(context); //this function calls all my API calls, but for testing, I commented out all other functions and kept only the one written above
        });
    }

我不太明白为什么。如果有人能给我解释一下,我会很高兴的

cqoc49vn

cqoc49vn2#

使用Consumer访问Provider的变量

return Consumer<YourProviderName>(builder : (context, value, child){
return value.isLoading? const Center(
    child: CircularProgressIndicator(),
  ):YourWidget(),
});

相关问题