(转)Flutter入门例子小记

原文:https://blog.csdn.net/u011728347/article/details/80880711 

一、尝试修改main.dart

main.dart中的代码替换为以下内容:

import 'package:flutter/material.dart';

void main() => runApp(new GHFlutterApp());


class GHFlutterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'GHFlutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('GHFlutter'),
        ),
        body: new Center(
          child: new Text('GHFlutter'),
        ),
      ),
    );
  }
}

顶部附近的main()函数使用=>运算符,为了单行函数运行应用程序。 您有一个名为GHFlutterApp的应用程序。
你在这里看到你的应用程序本身是一个StatelessWidget(无状态组件)。Flutter应用程序中的大多数实体都是组件,无论是无状态的还是有状态的。 您重写组件的build()方法来创建您的应用的组件。 您正在使用MaterialApp 组件,该组件提供了大量遵循Material Design规范应用组件。

组件分类:

Stateless: 仅依赖于自己的配置信息的组件,例如图像视图中的静态图像(上面就是这种组件)
Stateful: 需要维护动态信息的组件,并通过与状态对象交互来实现(下面就是这种组件)
--------------------------------以上为Stateless组件-----------------------------------

二、Stateful组件

要开始制作自己的组件,请在main.dart的底部创建一个新类:

class GHFlutter extends StatefulWidget {
  @override
  createState() => new GHFlutterState();
}

你已经创建了一个StatefulWidget子类,并且你重写了createState()方法来创建它的状态对象。 现在在GHFlutter上添加一个GHFlutterState类:

class GHFlutterState extends State<GHFlutter> {
}


GHFlutterState使用GHFlutter的参数扩展状态。

制作新组件时的主要任务是重写在组件呈现在屏幕上时调用的build()方法。

重写GHFlutterState 的build()方法:

@override
Widget build(BuildContext context) {
  return new Scaffold (
    appBar: new AppBar(
      title: new Text('GHFlutter2'),   
    ),
    body: new Text('GHFlutter2'),
  );
}

Scaffold 是material design组件的容器。 它充当组件层次结构的根。 您已将AppBar和一个body添加到scaffold中,并且每个都包含一个Text组件

更新GHFlutterApp,以便它使用新的GHFlutter组件作为其home属性,而不是构建默认的scaffold:

class GHFlutterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'GHFlutter',
      home: new GHFlutter(),
    );
  }
}

构建并运行应用程序,您将看到新的组件正在运行:

现在还没有多少变化,但是现在你已经开始构建新的组件。

三、网络请求和使用ListView

您现在将使用框架中的库来进行HTTP网络调用,并将生成的JSON响应解析为Dart对象。 在main.dart的顶部添加两个新的引入:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

您将进行异步网络调用以检索GitHub组织成员列表。 在GHFlutterState顶部添加一个空List作为属性,并添加一个属性来保存文本样式(_biggerFont):

var _members = [];

final _biggerFont = const TextStyle(fontSize: 18.0);

名字以下划线开头的变量表示类的私有成员变量。
要进行异步HTTP调用,请在GHFlutterState中添加一个_loadData()方法:

_loadData() async {
  String dataURL = "https://api.github.com/orgs/raywenderlich/members";
  http.Response response = await http.get(dataURL);
  setState(() {
    _members = JSON.decode(response.body);
  });
}

您已将async关键字添加到_loadData()中,以告诉Dart它是异步的,但是http.get()的await关键字表示阻塞执行。 通过dataUrl设置API的请求地址。

当HTTP调用完成时,您将回调传递给在UI线程上同步运行的setState()。 这时,您解码JSON响应并将其赋值给_members变量。
在GHFlutterState中重写initState方法,在initState中调用_loadData() 方法。当组件状态初始化时,_loadData()会被调用,加载数据。

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

  _loadData();
}

现在您已经有了成员列表(_members),您需要一种方法在列表UI中显示它们。 Dart提供了一个ListView组件,可让您在列表中显示数据。 ListView的作用类似于Android上的RecyclerView和iOS上的UITableView,通过重复回收利用以后的view,使列表滚动更加顺滑。
在GHFlutterState中添加_buildRow()方法:

Widget _buildRow(int i) {
  return new ListTile(
    title: new Text("${_members[i]["login"]}", style: _biggerFont)
  );
}

您将返回一个ListTile组件,该组件显示第iJSON成员的"login"值,还使用您之前创建的文本样式(_biggerFont)。

更新build方法,使body属性值为ListView.builder:

body: new ListView.builder(
  padding: const EdgeInsets.all(16.0),
  itemCount: _members.length,
  itemBuilder: (BuildContext context, int position) {
    return _buildRow(position);
  }),

您已添加padding,将itemCount设置为成员数量,设置itemBuilder调用_buildRow(),传递postion变量。

四、解析为自定义类型

JSON解析器将JSON响应中的每个成员都作为Dart Map类型实例添加到_members列表中,这相当于Kotlin中的Map或Swift中的Dictionary。
但是,如果你想使用自定义类。
在main.dart文件中添加Member类:

class Member {
  final String login;

  Member(this.login) {
    if (login == null) {
      throw new ArgumentError("login of Member cannot be null. "
          "Received: '$login'");
    }
  }
}

member有一个login属性,和一个构造函数,在构造函数中当login值为null时,会抛出一个error。
更新GHFlutterState类中的_members变量声明,所以现在他就是一个Member对象的list

var _members = <Member>[];
更新_buildRow()方法使用Member对象的login属性而不是map的"login"key的值。

title: new Text("${_members[i].login}", style: _biggerFont)
现在更新在_loadData()中的传递给setState()的回调,将map解析为Member对象,添加到member对象list中。

setState(() {
  final membersJSON = JSON.decode(response.body);

  for (var memberJSON in membersJSON) {
    final member = new Member(memberJSON["login"]);
    _members.add(member);
  }
});

五、Menber类中多一个参数用来加载图片

每个member都有一个头像url.你将添加头像到Member类中,然后在app中显示头像。

在Member类中添加avatarUrl属性,这个属性不能为null。

class Member {
  final String login;
  final String avatarUrl;

  Member(this.login, this.avatarUrl) {
    if (login == null) {
      throw new ArgumentError("login of Member cannot be null. "
          "Received: '$login'");
    }
    if (avatarUrl == null) {
      throw new ArgumentError("avatarUrl of Member cannot be null. "
          "Received: '$avatarUrl'");
    }
  }
}

更新_buildRow()方法,通过NetworkImage 和 the CircleAvatar 组件显示头像。

Widget _buildRow(int i) {
  return new Padding(
    padding: const EdgeInsets.all(16.0),
    child: new ListTile(
      title: new Text("${_members[i].login}", style: _biggerFont),
      leading: new CircleAvatar(
        backgroundColor: Colors.green,
        backgroundImage: new NetworkImage(_members[i].avatarUrl)
      ),
    )
  );
}

设置头像为ListTile的leading属性,头像将显示在title的前面。
更新_loadData()方法,使在创建一个新的Member时使用map的"avatar_url"值。

final member = new Member(memberJSON["login"], memberJSON["avatar_url"]);
构建运行,你将能看到每一个行的头像。

六、整理代码
大部分代码现在位于main.dart文件中。 为了使代码更清晰一点,你可以重构组件和你已经添加到他们自己的文件中的类。
在lib文件夹中创建名为member.dart和ghflutter.dart的文件。 将Member类移入member.dart,并将GHFlutterState和GHFlutter类转移到ghflutter.dart。

更新main.dart中的导入,所以整个文件包含以下内容:

import 'package:flutter/material.dart';

import 'ghflutter.dart';

void main() => runApp(new GHFlutterApp());
class GHFlutterApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'GHFlutter',
      home: new GHFlutter(),
    );
  }
}  

通过构建并运行应用程序,您应该看不到任何更改,但代码现在更清晰一些。

看完这篇文章,再看listView更复杂的写法就比较容易看懂了,例如这篇写ListView文章:

https://www.jb51.net/article/144579.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值