Saya telah mempelajari flutter selama beberapa bulan dan sekarang saya bereksperimen dengan Hooks dan Riverpod yang akan sangat penting sehingga beberapa hasil dapat di-cache oleh penyedia dan digunakan kembali dan hanya benar-benar diambil kembali ketika ada pembaruan.

Tapi saya mencapai titik di sini dengan masalah di mana saya tidak bisa memikirkan pembaruan penyedia untuk tercermin dalam Widget. Contoh lengkap dapat dilihat dari sini -> https://github.com/codespair/riverpod_update_issue Saya telah menambahkan beberapa pencetakan debug dan saya dapat melihat penyedia disegarkan dengan benar tetapi perubahannya tidak tercermin pada widget.

Contoh memiliki penyedia sampel yang berfungsi:

// create simple FutureProvider with respective future call next
final futureListProvider =
    FutureProvider.family<List<String>, int>((ref, value) => _getList(value));

// in a real case there would be an await call inside this function to network or local db or file system, etc...
Future<List<String>> _getList(int value) async {
  List<String> result = [...validValues];
  if (value == -1) {
    // do nothing just return original result...
  } else {
    result = []..add(result[value]);
  }
  debugPrint('Provider refreshed, result => $result');
  return result;
}

Daftar tarik-turun saat diubah menyegarkan penyedia:

             Container(
                  alignment: Alignment.center,
                  padding: EdgeInsets.fromLTRB(5, 2, 5, 1),
                  child: DropdownButton<String>(
                    key: UniqueKey(),
                    value: dropDownValue.value.toString(),
                    icon: Icon(Icons.arrow_drop_down),
                    iconSize: 24,
                    elevation: 16,
                    underline: Container(
                      height: 1,
                      color: Theme.of(context).primaryColor,
                    ),
                    onChanged: (String? newValue) {
                      dropDownValue.value = newValue!;
                      context
                          .refresh(futureListProvider(intFromString(newValue)));
                    },
                    items: validValues
                        .map<DropdownMenuItem<String>>((String value) {
                      return DropdownMenuItem<String>(
                        value: value,
                        child: Text(
                          value,
                          style: Theme.of(context).primaryTextTheme.subtitle1,
                        ),
                      );
                    }).toList(),
                  ),
                ),

Dan daftar sederhana yang menggunakan elemen penyedia untuk merender yang meskipun penyedia disegarkan dengan benar seperti yang Anda lihat di debugPrinting, penyedia tidak pernah diperbarui:

Container(
          key: UniqueKey(),
          height: 200,
          child: stringListProvider.when(
            data: (stringList) {
              debugPrint('List from Provider.when $stringList');
              return MyListWidget(stringList);
              // return _buildList(stringList);
            },
            loading: () => CircularProgressIndicator(),
            error: (_, __) => Text('OOOPsss error'),
          ),
        ),
      ]),


class MyListWidget extends HookWidget {
  final GlobalKey<ScaffoldState> _widgetKey = GlobalKey<ScaffoldState>();
  final List<String> stringList;

  MyListWidget(this.stringList);

  @override
  Widget build(BuildContext context) {
    debugPrint('stringList in MyListWidget.build $stringList');
    return ListView.builder(
      key: _widgetKey,
      itemCount: stringList.length,
      itemBuilder: (BuildContext context, int index) {
        return Card(
          key: UniqueKey(),
          child: Padding(
              padding: EdgeInsets.all(10), child: Text(stringList[index])),
        );
      },
    );
  }

Ketika saya mengevaluasi pendekatan untuk mengembangkan beberapa aplikasi, saya cenderung mengadopsi pendekatan yang lebih mudah untuk menangani kasus seperti itu, jadi saya juga terbuka untuk mengevaluasi pendekatan yang lebih sederhana dan lebih mudah, tetapi saya sangat menyukai beberapa fitur seperti useMemoized, useState dari hooks_riverpod .

0
groo 23 April 2021, 23:07

1 menjawab

Jawaban Terbaik

Satu hal yang ingin saya perhatikan sebelum kita mulai adalah Anda masih dapat menggunakan useMemoized, useState, dll. tanpa hooks_riverpod, dengan flutter_hooks.

Sejauh masalah Anda, Anda menyalahgunakan family. Saat Anda memasukkan nilai baru ke family, Anda sebenarnya membuat penyedia lain. Itulah mengapa daftar Anda dicetak dengan benar, karena memang demikian, tetapi hasil yang benar terjebak di ProviderFamily yang tidak Anda baca.

Pendekatan yang lebih sederhana adalah membuat StateProvider yang Anda gunakan untuk menyimpan nilai yang saat ini dipilih dan melihat penyedia itu dari FutureProvider Anda. Ini akan memperbarui daftar secara otomatis tanpa harus refresh.

final selectedItemProvider = StateProvider<int>((_) => -1);

final futureListProvider = FutureProvider<List<String>>((ref) async {
  final selected = ref.watch(selectedItemProvider).state;
  return _getList(selected);
});

DropdownButton<String>(
  ...
  onChanged: (String? newValue) {
    dropDownValue.value = newValue!;
    context.read(selectedItemProvider).state = intFromString(newValue);
  },
}
2
Alex Hartford 23 April 2021, 20:58