当Flutter App Skeleton中的详细信息视图更改状态时更新ListView

nxagd54h  于 2023-11-21  发布在  Flutter
关注(0)|答案(1)|浏览(153)

我有一个基于默认Flutter Skeleton Application的非常简单的flutter应用程序。它有一个名为SampleItemListView的ListView,当你点击列表中的一个项目时,它使用Navigator.restorablePushNamed导航到SampleItemDetailsView。列表视图构建方法看起来像这样,直接来自模板:
列表视图:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Sample Items'),
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () {
              Navigator.restorablePushNamed(context, SettingsView.routeName);
            },
          ),
        ],
      ),

      body: ListView.builder(
        // Providing a restorationId allows the ListView to restore the
        // scroll position when a user leaves and returns to the app after it
        // has been killed while running in the background.
        restorationId: 'sampleItemListView',
        itemCount: items.length,
        itemBuilder: (BuildContext context, int index) {
          final item = items[index];

          return ListTile(
            title: Text('SampleItem ${item.id}'),
            leading: const CircleAvatar(
              // Display the Flutter Logo image asset.
              foregroundImage: AssetImage('assets/images/flutter_logo.png'),
            ),
            onTap: () {
              // Navigate to the details page. If the user leaves and returns to
              // the app after it has been killed while running in the
              // background, the navigation stack is restored.
              Navigator.restorablePushNamed(
                context,
                SampleItemDetailsView.routeName,
              );
            }
          );
        },
      ),
    );
  }

字符串
查看详情:

class MarkdownNodeDetailsView extends StatefulWidget {
  const MarkdownNodeDetailsView({super.key});

  static const routeName = '/markdown';

  @override
  State<MarkdownNodeDetailsView> createState() =>
      _MarkdownNodeDetailsViewState();
}

class _MarkdownNodeDetailsViewState extends State<MarkdownNodeDetailsView> {
  MarkdownNode? node;

  @override
  void didChangeDependencies() {
    final args = ModalRoute.of(context)!.settings.arguments;
    if (args is Map && args['id'] != null) {
      findNodeById(int.parse(args['id']!)).then((value) {
        if (value != null) {
          setState(() {
            node = MarkdownNode(value.id!, value.properties['md']);
          });
        }
      });
    } else {
      node = MarkdownNode(-1, '');
    }
    super.didChangeDependencies();
  }

  @override
  void dispose() {
    saveToRemoteDb();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var txtController = TextEditingController();
    var txt = node?.md ?? '';
    // https://stackoverflow.com/questions/51127241/how-do-you-change-the-value-inside-of-a-textfield-flutter
    txtController.value = TextEditingValue(
      text: txt,
      selection: TextSelection.fromPosition(
        TextPosition(offset: txt.length),
      ),
    );

    return Scaffold(
      appBar: AppBar(
        title: const Text('Item Details'),
      ),
      body: Center(
        child: Column(
          children: [
            SizedBox(
              height: 200,
              child: TextField(
                controller: txtController,
                maxLines: null,
                expands: true,
                keyboardType: TextInputType.multiline,
                onChanged: (v) {
                  setState(() {
                    node?.md = v;
                  });
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}


我的应用程序引入了从详细信息视图更改项目的功能。它在详细信息视图上工作得很好,但是,当用户弹出回到列表视图时,列表视图并不反映更新的状态。
如果我直接示例化SampleItemDetailsView,我可以向它的构造函数传递一个回调函数,但我没有这样做,它是由Navigator示例化的。
当详细视图返回时,通知ListView它可能需要更新的正确方法是什么?

6tqwzwtp

6tqwzwtp1#

下面是一个使用provider包的示例

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

class ItemProvider extends ChangeNotifier {
  List<SampleItem> _items = [
    SampleItem(id: 1),
    SampleItem(id: 2),
    // Add more items as needed
  ];

  List<SampleItem> get items => _items;

  void updateItem(SampleItem item) {
    // Find the index of the item in the list
    int index = _items.indexWhere((element) => element.id == item.id);

    if (index != -1) {
      // Update the item in the list
      _items[index] = item;

      // Notify listeners that the state has changed
      notifyListeners();
    }
  }
}

class ItemsManager extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Items Manager'),
      ),
      body: Consumer<ItemProvider>(
        builder: (context, itemProvider, _) {
          return ListView.builder(
            itemCount: itemProvider.items.length,
            itemBuilder: (BuildContext context, int index) {
              final item = itemProvider.items[index];

              return ListTile(
                title: Text('SampleItem ${item.id} ${item.details}'),
                leading: CircleAvatar(
                  child: Icon(Icons.image),
                ),
                onTap: () async {
                  var result = await Navigator.restorablePushNamed(
                    context,
                    SampleItemDetailsView.routeName,
                  );

                  if (result != null && result is SampleItem) {
                    itemProvider.updateItem(result as SampleItem);
                  }
                },
              );
            },
          );
        },
      ),
    );
  }
}

class SampleItemDetailsView extends StatelessWidget {
  static const routeName = '/sampleItemDetails';

  @override
  Widget build(BuildContext context) {
    final itemProvider = Provider.of<ItemProvider>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Sample Item Details'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('Details for SampleItem'),
            ElevatedButton(
              onPressed: () {
                // Update the details of the first item
                SampleItem updatedItem = SampleItem(
                  id: itemProvider.items.first.id,
                  details: 'Updated details',
                );

                // Notify listeners and pop this view off the navigation stack
                itemProvider.updateItem(updatedItem);

                Navigator.pop(context, updatedItem);
              },
              child: Text('Update Item Details'),
            ),
          ],
        ),
      ),
    );
  }
}

class SampleItem {
  final int id;
  String details;

  SampleItem({required this.id, this.details = 'Initial details'});
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => ItemProvider(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ItemsManager(),
      routes: {
        SampleItemDetailsView.routeName: (context) => SampleItemDetailsView(),
      },
    );
  }
}

字符串

相关问题