快速開始
譯者注:在此章節中,由於 Provider 庫,Provider 類,Provider 及其相關的提供者程式類容易造成混淆,一般的,我們約定:
- Provider 庫 ->
pkg:Provider
/Provider
,和 Riverpod 一樣首字母大寫。 - Provider 類 ->
provider
,小寫,特指單純的提供者程式類 Provider。 - Provider 泛指 ->
提供者程式
,表示各種不同的提供者程式類都適用。
其他地方的代指某個 provider,會被具體翻譯,避免不必要的誤解,請放心閱讀。
如有翻譯錯誤還請 pr 指正。
本部分專為熟悉 Provider 包並希望瞭解 Riverpod 的人員而設計。
首先,請閱讀簡短的入門指南文章,並嘗試使用小型沙盒示例來測試 Riverpod 的功能。 如果您喜歡那裡看到的內容,那麼您應該明確考慮遷移。
事實上,從 Provider 遷移到 Riverpod 可以非常簡單。
遷移基本上包括幾個步驟,這些步驟可以以增量方式完成。
從 ChangeNotifierProvider
開始
在過渡到 Riverpod 時是可以的繼續使用,而不是儘快使用 ChangeNotifier
其最新的花哨功能。
事實上,可以從以下幾點著手開始:
// 如果你有這個……
class MyNotifier extends ChangeNotifier {
int state = 0;
void increment() {
state++;
notifyListeners();
}
}
// ……只需要加上這個!
final myNotifierProvider = ChangeNotifierProvider<MyNotifier>((ref) {
return MyNotifier();
});
正如你所看到的,Riverpod 公開了一個 ChangeNotifierProvider 類, 該類正是為了支援從 pkg:Provider 遷移。
請記住,在編寫新程式碼時不建議使用 ChangeNotifierProvider
,因為它不是使用 Riverpod 的最佳方式,
但它是開始遷移的一種溫和且非常簡單的方法。
不要急於立即嘗試將您的 ChangeNotifier
遷移到更現代的 Riverpod 的提供者程式。
有些地方會進行一些泛型的轉變,因此最初可能很難做到。
慢慢來,因為首先熟悉 Riverpod 很重要; 你很快就會發現,幾乎所有來自 pkg:provider 的提供者程式在 pkg:riverpod 中都有嚴格等價的程式碼。
從葉子開始
從不依賴於其他任何內容的提供者程式開始,即從依賴項樹中的葉子開始。
遷移完所有葉子後,可以轉到依賴於葉子的提供者程式。
換言之,首先要避免遷移 ProxyProvider
;當遷移了它們的所有依賴項,就可以開始處理它們了。
這應該促進和簡化遷移過程,同時還可以最大限度地減少/跟蹤任何錯誤。
Riverpod 和 Provider 可以共存
請記住,完全可以同時使用 Provider 和 Riverpod。
事實上,使用匯入別名,可以同時使用兩個 API 了。
這也非常有助於提高可用性,並消除了任何模稜兩可的 API 用法。
如果計劃執行此操作,請考慮對程式碼庫中的每個提供者程式匯入使用匯入別名。
關於如何有效實現匯入別名的完整指南即將釋出。
您不必立即使用 Consumer
請務必記住,無需立即使用 Riverpod 的 Consumer
API。
如果您剛剛開始遷移,如上所述,您可能應該從 ChangeNotifierProvider
開始。
考慮上面定義的 myNotifierProvider
。
由於您的內部程式碼可能依賴於 pkg:Provider 的 API,因此請使用以下程式碼開始使用 pkg:Riverpod 的 ChangeNotifier
。
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: ref.watch(myNotifierProvider.notifier)),
]
)
這樣,最初只需將根 Widget 轉換為 ConsumerWidget
。
這應該會進一步簡化向 pkg:Riverpod 的遷移。
一次遷移一個提供者程式
如果您已有應用,請不要嘗試一次遷移所有的提供者程式!
雖然從長遠來看,您應該努力將所有應用程式遷移到 Riverpod,但不要讓自己筋疲力盡。
一次只遷移一個提供者程式。
以上面的例子為例。將其 myNotifierProvider
完全遷移到 Riverpod 意味著需要編寫以下內容:
class MyNotifier extends Notifier<int> {
int build() => 0;
void increment() => state++;
}
final myNotifierProvider = NotifierProvider<MyNotifier, int>(MyNotifier.new);
……並且還需要更改這個 myNotifierProvider
的使用方式,即每個 context.watch
的位置替換為 ref.watch
。
此操作可能需要一些時間,並可能導致一些錯誤,因此不要急於一次完成所有操作。
遷移 ProxyProvider
在 pkg:Provider 中,ProxyProvider
用於組合來自其他提供者程式的值;
它的構建被動地取決於其他提供者程式的價值。
相反,在 Riverpod 中,提供者程式預設是可組合的;
因此,在遷移 ProxyProvider
時,如果要宣告從一個提供者程式到另一個提供者程式的直接依賴項,則只需編寫 ref.watch
即可。
如果有的話,將值與 Riverpod 相結合應該感覺更簡單明瞭;因此,遷移應該大大簡化程式碼。
此外,將兩個以上的提供者程式組合在一起沒有任何障礙:只需新增另一個 ref.watch
,就可以了。
預先初始化
由於 Riverpod 的提供者程式是全域性 final 變數,因此它們預設是懶載入的。
如果您需要在啟動時初始化一些預熱資料或有用的服務,
最好的做法是首次讀取提供者程式的時候,您手動去設定 MultiProvider
。
換句話說,由於 Riverpod 不能被強制預先初始化,因此可以在啟動階段讀取和快取它們, 以便在應用程式的其餘部分需要時它們完成了初始化並準備就緒。
有關 pkg:Riverpod 提供者程式的快速初始化的完整指南 [可在此處獲得]。
程式碼生成
建議使用程式碼生成,以便以面向未來的方式使用 Riverpod。
順便說一句,當元程式設計成為現實的時候,程式碼生成很可能是 Riverpod 的預設程式碼。
不幸的是, @riverpod
無法為 ChangeNotifierProvider
生成程式碼。
要解決此問題,您可以使用以下實用程式擴充套件方法:
extension ChangeNotifierWithCodeGenExtension on Ref {
T listenAndDisposeChangeNotifier<T extends ChangeNotifier>(T notifier) {
notifier.addListener(notifyListeners);
onDispose(() => notifier.removeListener(notifyListeners));
onDispose(notifier.dispose);
return notifier;
}
}
然後,您可以使用以下程式碼生成語法公開您的 ChangeNotifier
:
// ignore_for_file: unsupported_provider_value
MyNotifier example(Ref ref) {
return ref.listenAndDisposeChangeNotifier(MyNotifier());
}
完成“基本”遷移後,您可以將 ChangeNotifier
更改為 Notifier
,從而消除了臨時擴充套件的需要。
以前面的示例為例,“完全遷移” Notifier
變為:
class MyNotifier extends _$MyNotifier {
int build() => 0;
void increment() => state++;
}
一旦完成此操作,並且您確信程式碼庫中不再有 ChangeNotifierProvider
,您就可以徹底擺脫臨時擴充套件。
請記住,雖然是推薦的,但程式碼生成不是強制性的。
以增量方式進行遷移是個好的選擇:
如果您覺得在一次轉換到程式碼生成語法的同時實現此遷移可能太麻煩了,別勉強。
按照本指南,您可以稍後做進一步的遷移到程式碼生成。