Riverpod — mahiyyəti, Flutter-də asılılıqların kompilə edilməsi

Müəllif: IT Sectr Dərc olunub: 2026-02-19 Oxuma vaxtı: 7 dəq

Riverpod — Flutter üçün kompilə edilən vəziyyət və asılılıq meneceri, 2021-ci ildə Rémi Roussel tərəfindən Provider-in varisi olaraq yaradılmışdır. Riverpod Provider-in fundamental problemlərini həll edir: kompilə yoxlamasının olmaması, BuildContext-dən asılılıq və ProviderNotFoundException ilə çətinlik. pub.dev məlumatlarına görə, paket 5 mindən çox bəyənmə toplamış və yeni layihələrdə Provider-i aktiv şəkildə əvəz edir.

Əsas

  • ProviderRef — provider daxilində digər providerlərə daxil olmaq üçün obyekt
  • AsyncValue — loading/error/data vəziyyətləri ilə asinxron məlumatlar üçün sarğı
  • Notifier — dəyişmə metodları ilə mutasiya olunan vəziyyət üçün sinif
  • ProviderScope — bütün providerləri idarə edən kök vidjet
  • Code Generation — providerlərin avtomatik generasiyası üçün @riverpod anotasiyaları

Riverpod nədir?

Riverpod — Flutter-də vəziyyətin idarə edilməsi və asılılıqların daxil edilməsi üçün kitabxana, provider təsvirlərini təhlükəsiz Dart koduna kompilə edir. Provider-dən fərqli olaraq, Riverpod provider-ləri BuildContext-ə bağlı deyil: onlar qlobal olaraq və ya ProviderScope-də yaradılır və istənilən yerdən əlçatandır. Kompilator qurma mərhələsində provider qrafının növlərini, asılılıqlarını və bütövlüyünü yoxlayır və ProviderNotFoundException kimi runtime səhvlərini aradan qaldırır.

Riverpod test üçün override modelindən istifadə edir: hər bir provider alt siniflər yaratmadan və ya interfeysləri mock etmədən ProviderScope.overrideWith vasitəsilə ləğv edilə bilər. Bu, testi izolyasiya edir: hər test tam idarə olunan asılılıq qrafının öz nüsxəsini alır.

Flutter Community Survey 2025 məlumatlarına görə, Riverpod populyarlıq baxımından Provider və BLoC-dan sonra üçüncü yerdədir. Eyni zamanda Riverpod ən sürətli böyüyən paketdir: 2024-cü ildə +120% quraşdırma. Əsas səbəblər: kompilə təhlükəsizliyi, ProviderNotFoundException-nin olmaması, AsyncValue vasitəsilə asinxronluğun daxili dəstəyi.

Provider növləri

Riverpod hər biri konkret ssenari üçün 8 növ provider təqdim edir: Provider (sabit/xidmət), StateProvider (sadə vəziyyət), StateNotifierProvider (StateNotifier ilə mürəkkəb məntiq), ChangeNotifierProvider (Provider-dən miqrasiya üçün), FutureProvider (asinxron məlumatlar, bir dəfə), StreamProvider (reaktiv axın), NotifierProvider (yeni API, Flutter 3.10+) və AsyncNotifierProvider (asinxron Notifier).

Dart
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

class CounterScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Text('$count');
  }
}

ProviderRef — hər bir providerə digər providerlərə daxil olmaq üçün ötürülən obyekt. ref.watch — dəyişikliklərə abunə olmaq, ref.read — birdəfəlik oxumaq, ref.invalidate — keşi sıfırlamaq. ProviderRef Provider-dən BuildContext-i əvəz edir: istənilən provider vidjet ağacına daxil olmadan digər providerləri oxuya bilər. Bu, UI qatından kənarda asılılıq qrafı qurmağa imkan verir.

ProviderScope — Riverpod-un işləməsi üçün məcburi olan kök vidjet. ProviderScope bütün providerləri saxlayır, onların həyat dövrünü idarə edir və dəyərləri keşləyir. ProviderScope olmadan proqram ProviderNotFoundException ilə çökəcək. ProviderScope iç-içə ola bilər — iç-içə scopes valideyn providerlərini ləğv edir, bu da test və funksiyaların izolyasiyası üçün istifadə olunur.

AsyncValue və asinxronlukla iş

AsyncValue — asinxron vəziyyəti təmsil etmək üçün Riverpod-un sealed sinfi. AsyncValue-un üç variantı var: AsyncData (uğurlu məlumat), AsyncError (xəta), AsyncLoading (yüklənir). loading/error/data arasında əl ilə keçid etmək əvəzinə, hər FutureProvider və ya StreamProvider avtomatik olaraq AsyncValue qaytarır və vidjet ref.watch vasitəsilə hər üç vəziyyəti idarə edir.

Dart
final userProvider = FutureProvider((ref) async {
  final api = ref.watch(apiProvider);
  return await api.fetchUser();
});

class UserScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userAsync = ref.watch(userProvider);
    return userAsync.when(
      data: (user) => UserWidget(user),
      error: (e, _) => ErrorWidget(e.toString()),
      loading: () => CircularProgressIndicator(),
    );
  }
}

AsyncValue.when — hər üç vəziyyətin nümunə uyğunlaşdırılması üçün metod. Kompilator bütün üç halın idarə olunduğunu yoxlayır — loading və ya error unudularsa, kod kompilə olunmayacaq. AsyncValue.whenData — yalnız data üçün (loading/error lazım deyilsə). AsyncValue.guard — istisnanı AsyncError-ə çevirmək üçün try-catch sarğısı. keepAlive — görünmə diapazonundan çıxarkən provider keşinin məhv edilməsinin qarşısını alan bayraq.

Code Generation və @riverpod

Kodgenerasiya — Riverpod 2.0+-ın əsas xüsusiyyətidir. Funksiya üzərində @riverpod anotasiyası avtomatik olaraq düzgün tipə malik, refaktorinq dəstəyi və avtomatik tamamlama ilə provider yaradır. Kodgenerasiya riverpod_generatorbuild_runner istifadə edir. Tərtibatçı təmiz funksiya yazır, qalan hər şey — növlər, siniflər, fabrik konstruktorları — avtomatik generasiya olunur.

Dart
@riverpod
String helloWorld(HelloWorldRef ref) {
  return 'Hello World';
}

// Yaradıldı: final helloWorldProvider = Provider((ref) => 'Hello World');

@riverpod
class Counter extends _$Counter {
  int build() => 0;
  void increment() => state++;
}

Notifier — kodgenerasiya ilə mutasiya olunan vəziyyət üçün yeni API. Notifier build() metodu və vəziyyəti dəyişən metodları olan sinifdir. StateNotifier-dən fərqli olaraq, Notifier ayrıca vəziyyət sinfi tələb etmir və getter/setter vasitəsilə state-ə birbaşa giriş verir. Riverpod @riverpod anotasiyası olan hər Notifier sinfi üçün avtomatik NotifierProvider yaradır.

build_runner: kodgenerasiya dart run build_runner build əmri ilə işə salınır. Generasiya olunmuş fayllar .g.dart suffiksinə malikdir və mənbə koduna idxal olunur. Anotasiyalar və ya provider növləri dəyişdikdə kodgenerasiyanı yenidən işə salmaq lazımdır. Riverpod 2.x bütün yeni layihələr üçün kodgenerasiyanı tövsiyə edir — providerlərın əl ilə yaradılması köhnəlir.

Riverpod vs Provider

Əsas fərqlər Riverpod ilə Provider arasında: BuildContext-dən müstəqillik, kompilə təhlükəsizliyi, asinxronlukla daxili iş, avtomatik keşləmə və override vasitəsilə test. Provider vəziyyətə daxil olmaq üçün BuildContext tələb edir (context.watch, context.read), Riverpod WidgetRef və qlobal elan edilmiş providerlərdən istifadə edir.

XüsusiyyətProviderRiverpod
BuildContext-dən asılılıqBəliXeyr
Kompilə yoxlamasıXeyrBəli (@riverpod vasitəsilə)
ProviderNotFoundExceptionRuntimeMümkün deyil
AsinxronluqƏl iləAsyncValue (daxili)
TestProvider-də sarğıProviderScope.overrideWith
KeşləməXeyrAvtomatik + keepAlive

Provider-dən miqrasiya: Riverpod mövcud ChangeNotifier-ləri yenidən yazmadan istifadə etmək üçün ChangeNotifierProvider.adaptive-ni dəstəkləyir. Mərhələli miqrasiya: əvvəlcə yeni funksiyalar Riverpod-da yazılır, sonra köhnə Provider-lər adapter vasitəsilə Riverpod providerləri ilə əvəz olunur. Hər iki paket eyni layihədə birgə mövcud ola bilər ki, bu da inkişafı dondurmadan miqrasiyaya imkan verir.

Riverpod-un test edilməsi

Riverpod-un test edilməsi ProviderScope.overrideWith üzərində qurulub. Hər bir provider mock və DI konteynerləri olmadan test ProviderScope daxilində ləğv edilir. ProviderContainer — Flutter-siz (təmiz Dart) testlər üçün izolyasiya edilmiş mühit, providerləri vidjetləri göstərmədən test etməyə imkan verir.

Dart
import 'package:flutter_test/flutter_test.dart';
import 'package:riverpod/riverpod.dart';

void main() {
  test('Counter increments correctly', () {
    final container = ProviderContainer();
    container.read(counterProvider.notifier).increment();
    expect(container.read(counterProvider), 1);
  });

  testWidgets('UI updates on increment', (tester) async {
    await tester.pumpWidget(
      ProviderScope(
        overrides: [counterProvider.overrideWithValue(5)],
        child: CounterScreen(),
      ),
    );
    expect(find.text('5'), findsOneWidget);
  });
}

ProviderContainer — Flutter-siz. ProviderContainer-dan vidjetlər olmadan providerlərin vahid testləri üçün istifadə edin. overrideWithValue — providerı konkret dəyərlə əvəz etmək. overrideWith — provider fabriki ilə əvəz etmək (xidmətləri mock etmək üçün). autodispose — testlərdə providerın görünmə diapazonundan çıxdıqda container.dispose() ilə məhv olub-olmadığını yoxlayın.

Tez-tez verilən suallar

Riverpod BLoC-dan nə ilə fərqlənir?

Riverpod — qlobal providerlər, AsyncValue və kodgenerasiya ilə vəziyyətin idarə edilməsi kitabxanası. BLoC — Event → Stream → State ilə arxitektura nümunəsi. Riverpod öyrənmək daha asandır və @riverpod anotasiyaları vasitəsilə daha yaxşı DX təmin edir. BLoC biznes məntiqinin ciddi izolyasiyasını və BlocObserver vasitəsilə Event izləməni verir. Seçim layihənin paradigmasından asılıdır: Riverpod Provider-ə, BLoC isə reaktiv axınlara daha yaxındır.

Riverpod-da autodispose nədir?

Autodispose — heç kim abunə olmadıqda providerın avtomatik məhv edilməsi mexanizmi. Varsayılan olaraq bütün Riverpod providerləri autodispose-dir: vidjet ağacdan çıxdıqda provider yaddaşdan silinir. keepAlive — həmişə yaşamalı olan providerlar (API müştəriləri, repozitorilər, parametrlər) üçün autodispose-u söndürən bayraq. Bu, yaddaş sızmalarının qarşısını alır — istifadə olunmayan providerlar avtomatik məhv edilir.

ref.invalidate necə işləyir?

ref.invalidate — providerın keşini məcburi sıfırlayan metod. invalidate-dən sonra növbəti oxunuşda provider yenidən yaradılır: FutureProvider async funksiyasını təkrar icra edir, StreamProvider axına yenidən abunə olur. Məlumatları məcburi yeniləmək üçün invalidate istifadə edin (pull-to-refresh, istifadəçi dəyişikliyi). ref.refresh — invalidate + oxuma kombinasiyası: bir əməliyyatda keşi sıfırlayır və dərhal yeni dəyəri oxuyur.

Riverpod-dan kodgenerasiya olmadan istifadə etmək olar?

Bəli. Riverpod 1.x yalnız kodgenerasiya olmadan işləyir — providerlar əl ilə Provider(), StateNotifierProvider(), FutureProvider() və s. vasitəsilə yaradılır. Riverpod 2.x hər iki yanaşmanı dəstəkləyir. Kodgenerasiya olmadan daha çox boilerplate var, lakin build_runner və dart run build_runner build-dən asılılıq yoxdur. Kiçik layihələr (30 providera qədər) üçün əl ilə yaratmaq əsaslandırılmışdır, böyük layihələr üçün kodgenerasiya məcburidir.

Family-providerlar nədir?

Family — xarici parametr qəbul edən provider modifikatoru. Məsələn, userProvider(123) — ID-si 123 olan istifadəçini yükləyən provider. Family-providerlar hər unikal parametr üçün nəticəni ayrıca keşləyir. Family-dən hər bir elementin ID ilə yükləndiyi elementlər siyahısı üçün istifadə edin. Family modifikatoru bütün provider növləri üçün mövcuddur: Provider.family, FutureProvider.family, StreamProvider.family.

Xülasə

  • Riverpod — ProviderNotFoundException olmadan Provider-in varisi olan kompilə edilən vəziyyət meneceri
  • ProviderRef — digər providerlar daxilində providerlərə daxil olmaq üçün BuildContext əvəzedicisi
  • AsyncValue — asinxron məlumatlar üçün loading/error/data vəziyyətləri ilə sealed sinif
  • @riverpod kodgenerasiyası — növlərin və provider fabriklərinin avtomatik çıxarılması
  • ProviderScope.overrideWith — mock və DI konteynerləri olmadan izolyasiya edilmiş test
  • Family — fərdi keşləmə ilə parametrləşdirilmiş providerlar
  • autodispose və keepAlive — providerların həyat dövrünün avtomatik idarə edilməsi

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun