flutterdartstaterebuild

StateProvider does not rebuild when state changed


I have a serious problem with my Riverpod. Specifically, I am using StateProvider in Riverpod package. But when I update state, the widget tree does not rebuild. I checked the new state whether is updated by printing out state to see, I see that they are actually updated. I have some same situations but when I click hot restart/reload page/scroll up,down mouse to change size chrome window, the widget tree rebuild one time. Please help me and explain everything the most detail and easy to understand. Thank you very much new state print out but UI not update

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:math';
void main() {
  runApp(const ProviderScope(child: MyApp()));
}

class Data {
  final String data;
  Data({required this.data});
}
final helloWorldProvider = StateProvider<Data?>((ref) => Data(data: 'No data'));

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

  @override
  ConsumerState<MyApp> createState() => _MyAppState();
}
class _MyAppState extends ConsumerState<MyApp> {
  @override
  void initState() {
    // TODO: implement initState4
    print("Init state");
    super.initState();
    // getData();
  }
  // getData() async {
  //   // http.Response response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/todos/1'));
  //   // final title = jsonDecode(response.body)["title"];;
  //   // ref.read(helloWorldProvider.notifier).update((state) => title);
  //   SharedPreferences prefs = await SharedPreferences.getInstance();
  //   prefs.setString('valueTemp', 'newValue');
  //   String? valueTemp = prefs.getString('valueTemp');
  //   String value = valueTemp ?? '';
  //   Data data = Data(data: value);
  //   ref.read(helloWorldProvider.notifier).update((state) => data);
  //   print("Đã thực hiện xong");
  // }

  void _change() {
    print("change");
    final rawString = generateRandomString(5);
    Data data = new Data(data: rawString);
    ref.watch(helloWorldProvider.notifier).update((state) => data);
    print(ref.read(helloWorldProvider.notifier).state?.data);
  }

  String generateRandomString(int len) {
    var r = Random();
    return String.fromCharCodes(List.generate(len, (index) => r.nextInt(33) + 89));
  }

  @override
  Widget build(BuildContext context) {
    print('Rebuild');
    final data = ref.watch(helloWorldProvider.notifier).state;
    final dataText = data?.data ?? 'No text';
    print(dataText);
    return MaterialApp(
        title: 'Google Docs Clone',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: Center(
              child: Column(children: [
                Text(dataText)
              ]
              )
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _change,
            tooltip: 'Change',
            child: const Icon(Icons.add),
          ),
        ));
  }

}



I don't want to use other pattern as Provider, Bloc, StateNotifierProvider, ChangeNotifierProvider... I only want to run StateProvider successfully. I have refered to many articles and stackoverflows answer but I did't found any useful helps to my case.


Solution

  • final data = ref.watch(helloWorldProvider.notifier).state;
    

    is watching the notifier, which rarely changes. You want to watch the state change, as in:

    final data = ref.watch(helloWorldProvider);