skip to Main Content

As per the official document StateNotifierProvider it’s working fine, but I have a scenario to pass some value at the initial stage, flow is going like this, I have a list of items, and after clicking on it, it will be redirected to the details screen, when user swipe left or right with PageView.builder title hast be updated, it’s working fine when user swipe the page, but when user clicks on the 3rd item from the list I want to show title with the selected item, so I want to pass initial position to StateNotifierProvider

class ControllerPositionNotifier extends StateNotifier {
final currentPosition;

  ControllerPositionNotifier(this.currentPosition) : super(currentPosition);

  int position(int position) {
    return state = position;
  }
}

I want to pass a my value when I enter into widget ControllerPositionNotifier(MY_ARG)

 final controllerPositionNotifier = StateNotifierProvider<ControllerPositionNotifier, int>((ref) {
      return ControllerPositionNotifier(0);
    });

View pager screen

class SongWidget extends ConsumerStatefulWidget {
  final List<dynamic>? resultData;
  final int position;

  const SongWidget({Key? key, required this.resultData, required this.position})
      : super(key: key);

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

class _SongWidgetState extends ConsumerState<SongWidget> {


  @override
  Widget build(BuildContext context) {
    final songs = widget.resultData?.map((e) => Song.fromJson(e)).toList() ??
        List<Song>.empty();

    int position = ref.watch(controllerPositionNotifier);

    // HERE I WANT TO PASS ON MY ARGUMENT widget.position
   
    final PageController controller =
        PageController(initialPage: widget.position);

    print('_SongWidgetState');
    return Scaffold(
      appBar: AppBar(
        title: Text(songs[position].sTitle ?? '--'),
      ),
      body: PageView.builder(
        controller: controller,
        itemCount: songs.length,
        onPageChanged: (index) {
          print('position: $index');
          ref.watch(controllerPositionNotifier.notifier).position(index);
        },

        itemBuilder: (context, index) {
          return SingleChildScrollView(
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(16),
                  child: Text(
                    songs[index].sSong ?? '--',
                  ),
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

This line hast be updated the initial stage

appBar: AppBar(
        title: Text(songs[position].sTitle ?? '--'),
      )

After swipe updating successfully

ref.watch(controllerPositionNotifier.notifier).position(index);

But I would like to pass some value at the initial stage

2

Answers


  1. Chosen as BEST ANSWER

    To provide initial value when I get into the widget, I did update the provider before entering into the widget

    child: ListView.builder(
                                itemCount: dataValue.length,
                                itemBuilder: (context, index) {
                                  return InkWell(
                                      onTap: () {
                                        ref
                                            .watch(
                                                controllerPositionNotifier.notifier)
                                            .position(index);
                                        final result =
                                            Song.fromJson(dataValue[index]);
                                        Navigator.push(
                                            context,
                                            MaterialPageRoute(
                                                builder: (context) => SongWidget(
                                                      resultData: dataValue,
                                                      position: index,
                                                    )));
                                      },
                                      child: SongItem(data: dataValue[index]));
                                },
                              ),
    

    I did update the value, inside onTap() before moving to the SongWidget

    ref.watch(controllerPositionNotifier.notifier).position(index);
    

    onTap() - method

    return InkWell(onTap: () {
         ref.watch(controllerPositionNotifier.notifier).position(index);
      });
    

  2. Use the new api from riverpod 2.0 to pass the parameter:

    final controllerPositionNotifier = NotifierProviderFamily<ControllerPositionNotifier, int, int>(
        ControllerPositionNotifier.new,
      );
    
    class ControllerPositionNotifier extends FamilyNotifier<int, int> {
    
      @override
      int build(int index) {
        // here you can safely watch on providers
        return index;
      }
    }
    

    In the widget it will look like this:

    
    
    @override
      Widget build(BuildContext context) {
    
        int position = ref.watch(controllerPositionNotifier(widget.position));
       
        final PageController controller =
            PageController(initialPage: position);
        ...
    }
    

    Note: use ref.read in the callbacks

    ref.read(controllerPositionNotifier(position).notifier).position(index);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search