skip to Main Content

I’m using Riverpod with StateProvider for my app.

The home page will change based on tabs clicked.
When i click the ListTile tab to trigger the ref.read, it rebuild super fast:
But when i click the leading IconButton in Appbar which trigger ref.read(countProvider.notifier).state = 0; it takes me fews seconds to reload the back to 0. How do i fix this?
Full code:
layout.dart:

Set<Widget> _pages = {
  const HomeUI(),
  const FAQ(),
  const Setting(),
};

class Layout extends ConsumerStatefulWidget {
  const Layout({super.key});

  @override
  LayoutState createState() => LayoutState();
}

class LayoutState extends ConsumerState<Layout> {

  bool isHome = true;

  @override
  Widget build(BuildContext context) {
    final tab = ref.watch(countProvider);
    if (tab != 0) {
      isHome = false;
    } else {
      isHome = true;
    }
    return Scaffold(
      drawer: const Sidebar(),
      appBar: isHome
          ? AppBar(
              leading: Builder(builder: (context) {
                return IconButton(
                  icon: const Icon(FontAwesomeIcons.bars),
                  color: CustomColors.mainText,
                  onPressed: () {
                    Scaffold.of(context).openDrawer();
                  },
                );
              }),
              actions: [
                Padding(
                  padding: const EdgeInsets.only(right: 20),
                  child: IconButton(
                    icon: const Icon(FontAwesomeIcons.magnifyingGlass),
                    color: CustomColors.mainText,
                    onPressed: () {},
                  ),
                ),
              ],
              backgroundColor: Colors.transparent,
            )
          : null,
      backgroundColor: CustomColors.background,
      body: Stack(children: <Widget>[
        _pages.elementAt(tab),
        const MiniPlayer(),
      ]),
    );
  }
}

faq_screen.dart

class FAQ extends StatelessWidget {
  const FAQ({super.key});

  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, ref, child) {
        return Scaffold(
          appBar: AppBar(
            leading: IconButton(
              icon: const Icon(Icons.arrow_back),
              onPressed: () {
                ref.read(countProvider.notifier).state = 0;
              },
            ),
            title: const Text('FAQ'),
          ),
          body: const Center(
            child: Text('FAQ'),
          ),
        );
      },
    );
  }
}

sidebar.dart

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

import '../utilities/color.dart';
import '../utilities/provider.dart';

class Sidebar extends StatelessWidget {
  const Sidebar({super.key});

  @override
  Widget build(BuildContext context) {
    return Drawer(
      backgroundColor: CustomColors.background,
      child: Consumer(
        builder: (context, ref, child) => ListView(
          padding: EdgeInsets.zero,
          children: <Widget>[
            UserAccountsDrawerHeader(
              accountName: const Text("Wolhaiksong",
                  style: TextStyle(
                      color: Colors.white,
                      fontFamily: 'Gilroy',
                      fontWeight: CustomColors.semiBold)),
              accountEmail: const Text("[email protected]",
                  style: TextStyle(
                      color: Colors.white,
                      fontFamily: 'Gilroy',
                      fontWeight: CustomColors.regular)),
              currentAccountPicture: CircleAvatar(
                child: ClipOval(
                  child: Image.asset('assets/user.jpg'),
                ),
              ),
              decoration: const BoxDecoration(
                image: DecorationImage(
                    image: AssetImage('assets/wallpaper.jpg'),
                    fit: BoxFit.cover),
              ),
            ),
            ListTile(
              leading: const Icon(
                FontAwesomeIcons.lightbulb,
                color: CustomColors.gray,
              ),
              title: const Padding(
                padding: EdgeInsets.all(15.0),
                child: Text('FAQs',
                    style: TextStyle(
                      color: CustomColors.mainText,
                      fontWeight: CustomColors.semiBold,
                      fontFamily: 'Gilroy',
                    )),
              ),
              onTap: () {
                ref.read(countProvider.notifier).state = 1;
                Navigator.pop(context);
              },
            ),
            ListTile(
              leading: const Icon(
                FontAwesomeIcons.gear,
                color: CustomColors.gray,
              ),
              title: const Padding(
                padding: EdgeInsets.all(15.0),
                child: Text('Settings',
                    style: TextStyle(
                      color: CustomColors.mainText,
                      fontWeight: CustomColors.semiBold,
                      fontFamily: 'Gilroy',
                    )),
              ),
              onTap: () {
                ref.read(countProvider.notifier).state = 2;
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
    );
  }
}

provider.dart

final countProvider = StateProvider<int>((ref) {
  return 0;
});

2

Answers


  1. Chosen as BEST ANSWER

    I'm sorry guys, turns out the problem is not Riverpod but the async function i used to extract dominant color from the image.

    static Future<Color> generatePaletteColor(url) async {
        final PaletteGenerator paletteGenerator =
            await PaletteGenerator.fromImageProvider(
          AssetImage(url),
        );
        return paletteGenerator.paletteColors[0].color;
      }
    

    And I use it in initState so it runs everytime countProvider change

    @override
      void initState() {
        super.initState();
        CustomColors.generatePaletteColor(widget.song.artWork).then((value) {
          if (mounted) {
            setState(() {
              glowColor = value;
            });
          }
        });
      }
    

    Is there anyway to move the async function outside of this or prevent initState from rerun everytime rebuilt?


  2. Since you basically want to reset your provider to 0, instead of setting the value directly, you can try this:

    ref.refresh(countProvider);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search