如何在另一个类中使用setState?

时间:2019-06-27 00:33:17

标签: flutter dart

我在设置变量状态时遇到问题,因为我正在使用stateful小部件之外的其他类。
buildActions方法内的第115行,我想设置_selectedStores = selectedStores;。如何设置状态?
我尝试使用callback,但是没有运气。

import 'package:flutter/material.dart';

class SearchDemo extends StatefulWidget {
  @override
  _SearchDemoState createState() => _SearchDemoState();
}

class _SearchDemoState extends State<SearchDemo> {
  final _SearchDemoSearchDelegate _delegate = _SearchDemoSearchDelegate();
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  String _lastSearchSelected;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: const Text('Search Demo'),
        actions: <Widget>[
          IconButton(
            tooltip: 'Search',
            icon: const Icon(Icons.search),
            onPressed: () async {
              final String selected = await showSearch<String>(
                context: context,
                delegate: _delegate,
              );
              if (selected != null && selected != _lastSearchSelected) {
                setState(() {
                  _lastSearchSelected = selected;
                });
              }
            },
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Last search: ${_lastSearchSelected ?? 'NONE'}.'),
          ],
        ),
      ),
    );
  }
}

class Stores {
  int id;
  String name;

  Stores(this.id, this.name);

  static List<Stores> getStores() {
    return <Stores>[
      Stores(1, 'Amazon'),
      Stores(2, 'Flipkart'),
      Stores(3, 'Snapdeal'),
    ];
  }
}

class _SearchDemoSearchDelegate extends SearchDelegate<String> {
  List<Stores> _stores = Stores.getStores();
  List<DropdownMenuItem<Stores>> _dropdownMenuItems;
  Stores _selectedStores;

  List<DropdownMenuItem<Stores>> buildDropdownMenuItems(List stores) {
    List<DropdownMenuItem<Stores>> items = List();
    for (Stores stores in stores) {
      items.add(
        DropdownMenuItem(
          value: stores,
          child: Text(stores.name),
        ),
      );
    }
    return items;
  }

  @override
  Widget buildLeading(BuildContext context) {
    return IconButton(
      tooltip: 'Back',
      icon: AnimatedIcon(
        icon: AnimatedIcons.menu_arrow,
        progress: transitionAnimation,
      ),
      onPressed: () {
        close(context, null);
      },
    );
  }

  @override
  Widget buildSuggestions(BuildContext context) {
    return _SuggestionList(
      query: query,
      onSelected: (String suggestion) {
        print(suggestion);
      },
    );
  }

  @override
  Widget buildResults(BuildContext context) {}

  @override
  List<Widget> buildActions(BuildContext context) {
    _dropdownMenuItems = buildDropdownMenuItems(_stores);
    _selectedStores = _dropdownMenuItems[0].value;
    void onChangeDropdownItem(Stores selectedStores) {
      setState(() {
        _selectedStores = selectedStores;
      });
    }

    return <Widget>[
      query.isEmpty
          ? Container(
              padding: const EdgeInsets.only(right: 5.0, top: 5.0),
              child: DropdownButtonHideUnderline(
                child: DropdownButton(
                  elevation: 0,
                  value: _selectedStores,
                  items: _dropdownMenuItems,
                  onChanged: onChangeDropdownItem,
                ),
              ),
            )
          : IconButton(
              tooltip: 'Clear',
              icon: const Icon(Icons.clear),
              onPressed: () {
                query = '';
              },
            ),
    ];
  }
}

List<String> getHistory() {
  //Get Last Searched products from device storage *Pending*
  final List<String> _history = <String>[
    "iPhone X 64GB Silver",
    "Galaxy S10+ White",
    "Apple Watch Series 3",
    "Samson C01UPRO",
    "Cooler Master masterbox 5"
  ];
  return _history;
}

class _SuggestionList extends StatelessWidget {
  const _SuggestionList({this.query, this.onSelected});

  final String query;
  final ValueChanged<String> onSelected;

  @override
  Widget build(BuildContext context) {
    //Get Data From API *Pending*
    final List<String> _data = <String>[
      "iPhone X 64GB Silver",
      "Galaxy S10+ White",
      "Apple Watch Series 3",
      "Samson C01UPRO",
      "Cooler Master Masterbox 5"
    ];
    final List<String> suggestions = query.isEmpty
        ? getHistory()
        : _data
            .where((p) => p.toLowerCase().contains(query.toLowerCase()))
            .toList();
    return ListView.builder(
      itemCount: suggestions.length,
      itemBuilder: (BuildContext context, int i) {
        final String suggestion = suggestions[i];
        return ListTile(
          leading: query.isEmpty ? const Icon(Icons.history) : const Icon(null),
          title: Text(suggestion),
          onTap: () {
            onSelected(suggestion);
          },
        );
      },
    );
  }
}

1 个答案:

答案 0 :(得分:0)

方法setState只是StatefulWidgets的一部分,因此不应传递信息。不推荐这样做,它也不是一个好的开发实践。你可以做到吗?是的,像这样:

class OtherClass {
  final State state;

  OtherClass(this.state);
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {

  @override
  void initState() {
    super.initState();

    OtherClass(this);
  }
}

但是,再次,我完全不建议这样做。您应该使用某种FutureStream将数据发送到StatefulWidget,然后在应有的位置使用setState