【问题标题】:custom navigation drawer that loads its items via http does not render通过 http 加载其项目的自定义导航抽屉不会呈现
【发布时间】:2019-10-14 23:32:48
【问题描述】:

我有一个新生成的 Flutter 应用程序,其侧边栏又名导航抽屉。我不想拥有静态的、预定义的列表项,我想查询一个 http 服务来用我从服务接收到的数据填充列表项。

main.dart 几乎是生成的文件,没有抽屉。相反,我创建了一个包含 StatefulWidget 及其状态的 sidedrawer.dart。还有http服务。

main.dart:

import 'package:flutter/material.dart';
import 'package:mobilesite_flutter/sidedrawer.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      drawer: SideDrawer(),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

sidedrawer.dart:

import 'package:flutter/material.dart';
import 'package:mobilesite_flutter/tag.dart';
import 'dart:developer';


class SideDrawer extends StatefulWidget {
  @override
  createState() => _SideDrawerState();
}

class _SideDrawerState extends State<SideDrawer> {
  var tags = new List<Tag>();

  _getTags() {
    log('loading tags');
    TagService.findAll().then((value) => this.tags = value);
    log('tags loaded');
    for (var tag in this.tags) {
      log(tag.toString());
    }
  }

  initState() {
    super.initState();
    _getTags();
  }


  dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Drawer(
        child: ListView.builder(
          padding: EdgeInsets.zero,
          itemCount: this.tags.length,
          itemBuilder: (context, index) {
            log(this.tags.toString()); // <-- never called
            return ListTile(title: Text(this.tags[index].name));
          },
        )
    );
  }
}

还有服务:

import 'dart:convert';
import 'package:http/http.dart' as http;

class Tag {
  final String name;
  final String slug;

  Tag({this.name, this.slug});

  factory Tag.fromJson(Map<String, dynamic> json) {
    return Tag(
      name: json['name'],
      slug: json['slug'],
    );
  }

}

class TagService {
  static Future<List<Tag>> findAll() async {
    final response = await http.get('https://somedomain.com/api/v1/tags/');

    if (response.statusCode == 200) {
      Iterable list = json.decode(response.body);
      return list.map((model) => Tag.fromJson(model)).toList();
    } else {
      throw Exception('Failed to load tags');
    }
  }
}

我几乎是根据我在网上找到的东西把这些粘在一起的。

怎么了?当我按下汉堡时,抽屉是白色的。 在 sidedrawer.dart 中,我标记了从未执行过的部分。 遗憾的是,我不能在 promise 成功回调中使用 log(),因为它抱怨我应该升级到更高版本(我不记得的东西)。

我设置了 CORS,这不是问题,我有一个 Angular 应用程序可以从中获取数据,并且该应用程序可以完美运行。当我记录从 Web 服务端点(使用 toString())返回的内容时,我收到许多“标签实例”,因此有数据。但是_SideDrawerState 的构建方法似乎从未被调用过。

我必须怎么做才能渲染从 Web 服务加载的项目?

附言 最终的“产品”应该是卡片的初始虚拟滚动列表,侧面应该有一个标签列表,内容与之相关联,当我点击一个标签时,它应该按标签 slug 过滤内容,当我点击一张卡片时它应该打开一个新视图,该视图应该显示内容详细信息。非常类似于博客。但现在我很乐意将标签保存在它自己的有状态小部件中,它应该提供导航。

【问题讨论】:

    标签: flutter


    【解决方案1】:

    当然...在我发布问题后,我自己找到了答案。

    我当然要用setState(callbackFn())更新小部件的状态

      _getTags() {
        TagService.findAll().then((value) => setState(()=> {tags = value}));
      }
    

    但是我不得不更新 pubspec.yaml 文件,因为 Android Studio IDE 显示了警告。

    "直到 2.2 版才支持设置字面量,但这段代码是 需要能够在早期版本上运行。尝试更新 SDK 约束。”

    它仍然与

    一起运行
    environment:
      sdk: ">=2.1.0 <3.0.0"
    

    但警告就在这里。

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 2020-06-29
      • 1970-01-01
      • 1970-01-01
      • 2022-06-30
      • 1970-01-01
      相关资源
      最近更新 更多