首页 > 解决方案 > 为什么 context.select 只在 ListView.builder 包含在列中时更新 UI

问题描述

删除 ListView.builder 后,context.select不会更新 Ui。想知道为什么会这样。

import 'package:flutter/material.dart';
import 'dart:math';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (context) => ListProvider(),
        ),
        ChangeNotifierProxyProvider<ListProvider, ListReceiver>(
          create: (context) => ListReceiver(),
          update: (_, listProvider, listReceiver) =>
              listReceiver..displayList(listProvider.firstList),
        )
      ],
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        initialRoute: '/',
        routes: {
          '/': (context) => FirstPage(),
        },
      ),
    );
  }
}

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('This is a ProxyProvider test'),
      ),
      body: Builder(
        builder: (context) => Column(
          children: [
            ElevatedButton(
              onPressed: () {
                context.read<ListProvider>().addToList();
              },
              child: Text('add to list'),
            ),
            ListTile(
              title: Consumer<ListReceiver>(
                builder: (_, a, child) => Text(a.secondList.toString()),
              ),
              subtitle: Text(
                context.select((ListReceiver l) => l.secondList).toString(),
              ),
            ),
            SizedBox(
              height: 300,
              child: ListView.builder(
                itemCount:
                    context.select((ListReceiver d) => d.secondList.length),
                itemBuilder: (context, index) {
                  return Builder(
                      builder: (context) => ListTile(
                            title: Text(context.select((ListReceiver d) =>
                                d.secondList[index].toString())),
                            subtitle: Text('hi'),
                          ));
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class ListProvider extends ChangeNotifier {
  List firstList = [];
  var random = Random();

  void addToList() {
    firstList.add(random.nextInt(100));
    notifyListeners();
  }
}

class ListReceiver extends ChangeNotifier {
  List secondList;
  void displayList(List firstList) {
    secondList = firstList;
    notifyListeners();
    print(secondList);
  }
}

标签: flutterdartflutter-provider

解决方案


我无法解释你的观察者行为:(

对于它的价值,更换:

        ListTile(
          title: Consumer<ListReceiver>(
            builder: (_, a, child) => Text(a.secondList.toString()),
          ),
          subtitle: Text(
            context.select((ListReceiver l) => l.secondList).toString(),
          ),
        ),

和:

        ListTile(
          title: Text(context.watch<ListReceiver>().secondList.toString()),
          subtitle: Text(
            context.select((ListReceiver l) => l.secondList).toString(),
          ),
        ),

确实有效。


推荐阅读