dartpub.dev DartNative · beta
plugins / riverpod_kit
ri

riverpod_kit

v0.1.0 MIT

Riverpod for DartNative: flutter_riverpod's ProviderScope, ConsumerWidget and WidgetRef, working on pushed routes and sheets.

riverpod_kit rebuilds flutter_riverpod's widget layer on DartNative with the same names, so Riverpod code ports by changing one import. - ProviderScope, UncontrolledProviderScope, ConsumerWidget, ConsumerStatefulWidget / ConsumerState, Consumer. - WidgetRef: watch, read, listen, listenManual, refresh, invalidate, exists. - Works on pushed routes and in modal sheets: those are separate widget trees in DartNative, and riverpod_kit falls back to the app's root container, so consumers behave the same on every screen. - Riverpod itself is unchanged: providers, Notifier/AsyncNotifier, families, riverpod_annotation and riverpod_generator all work. Dart-only: no native code or permissions; iOS and Android. Depends on riverpod ^3.0.0. License: MIT. The API mirrors flutter_riverpod by Remi Rousselet (MIT); independent implementation.

by AbdurahmanAlmehdi/riverpod_kit · DartNative ≥ 3.0 · updated 4 days ago
Install
Free
pubspec.yaml
dependencies:
  riverpod_kit:
    hosted: https://dartpub.dev
    version: ^0.1.0
Weekly installs
0
Active apps
0
Rating
0.0 · 0
Open issues
0

riverpod_kit

Riverpod for DartNative apps. It rebuilds flutter_riverpod's widget layer on DartNative with the same names, so code written for Flutter's Riverpod ports by changing one import.

// import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_kit/riverpod_kit.dart';

Riverpod itself is used unchanged: providers, Notifier, AsyncNotifier, families, riverpod_annotation and riverpod_generator.

Why this package

  • Every flutter_riverpod widget you use daily. ProviderScope, UncontrolledProviderScope, ConsumerWidget, ConsumerStatefulWidget / ConsumerState, Consumer, and WidgetRef with watch, read, listen, listenManual, refresh, invalidate and exists.
  • Works on pushed screens and in sheets. In DartNative, a route pushed with Navigator.push and the body of showModalSheet are separate widget trees, so an inherited lookup from inside them never reaches the ProviderScope around your root screen. riverpod_kit falls back to the app's root container, so a ConsumerWidget behaves the same on any screen or sheet.
  • Rebuilds only what it must. Subscriptions made during a build are replaced on the next build, so a provider a widget no longer watches stops rebuilding it.
Home Pushed screen and sheet
home sheet

Install

dependencies:
  riverpod_kit:
    hosted: https://dartpub.dev
    version: ^0.1.0
dn pub get

Add riverpod_annotation and riverpod_generator as usual if you use code generation; they need nothing DartNative-specific.

Use

import 'package:dartnative/dartnative.dart';
import 'package:riverpod_kit/riverpod_kit.dart';

import 'dartnative_plugin_registrant.dart';

final counterProvider = NotifierProvider<Counter, int>(Counter.new);

class Counter extends Notifier<int> {
  @override
  int build() => 0;

  void increment() => state++;
}

void main() {
  DartNativePluginRegistrant.registerAll();
  runApp(const ProviderScope(child: HomeScreen()));
}

class HomeScreen extends ConsumerWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Scaffold(
      body: Center(
        child: Button(
          title: 'Count: $count',
          onPressed: () => ref.read(counterProvider.notifier).increment(),
        ),
      ),
    );
  }
}

A container built before runApp

Create the container yourself when startup must await something first (restoring a session, reading stored settings) or needs overrides. You own it and dispose it.

Future<void> main() async {
  DartNativePluginRegistrant.registerAll();
  final container = ProviderContainer(overrides: [/* ... */]);
  await container.read(sessionProvider.future);
  runApp(UncontrolledProviderScope(container: container, child: const App()));
}

Stateful widgets

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

  @override
  ConsumerState<DetailScreen> createState() => _DetailScreenState();
}

class _DetailScreenState extends ConsumerState<DetailScreen> {
  @override
  void initState() {
    super.initState();
    ref.listenManual(counterProvider, (previous, next) => dnLog('$next'));
  }

  @override
  Widget build(BuildContext context) =>
      Text('Count: ${ref.watch(counterProvider)}');
}

Outside the widget tree

ProviderScope.containerOf(context) returns the nearest container, else the root one. ProviderScope.rootContainer is the root container, or null before any scope is mounted.

Rules

They are the same as flutter_riverpod's:

  • Call ref.watch and ref.listen only inside build.
  • Use ref.listenManual in initState and callbacks; it is closed with the widget.
  • Don't use ref after dispose. It throws, as in Flutter. This includes setState or ref calls in an async callback that finishes after the screen has gone.

Example

example/lib/main.dart shows one counter shared by a root screen, a pushed ConsumerStatefulWidget and a Consumer inside a sheet.

cd example && dn run

Differences from flutter_riverpod

  • ProviderScope.rootContainer and the root fallback are additions. Flutter doesn't need them, because its routes inherit from above the app.
  • The ProviderScope parent, if any, is the nearest scope above, else the root container. There is no parent: parameter.

Credits

The API mirrors flutter_riverpod by Remi Rousselet (MIT). This package is an independent implementation on DartNative and depends on riverpod unchanged.

License

MIT, see LICENSE.