flutter 开发一个应用 1

基于gank的api,做一个应用,包含普通应用用到的功能.

构建一个gank干货的列表. https://github.com/lijinshanmx/flutter_gank/ 这是他的官方应用.

首先列表的构建前面的翻译的文章已经有了.这里不多说了.先解析干货的数据:

使用的是http://gank.io/api/today这个地址.

返回的结构是:

{
   "category": [
   "App",
   "iOS",
   "拓展资源",
   "瞎推荐",
   "Android",
   "前端",
   "福利",
   "休息视频"
   ],
   "error": false,
   "results": {
   "Android": [
   {
   "_id": "5bbb01af9d21226111b86f0d",
   "createdAt": "2018-10-08T07:05:19.297Z",
   "desc": "适用于Android的灵活,强大且轻量级的插件框架【爱奇艺】",
   "publishedAt": "2019-04-10T00:00:00.0Z",
   "source": "chrome",
   "type": "Android",
   "url": "https://github.com/iqiyi/Neptune",
   "used": true,
   "who": "潇湘剑雨"
   }],
   App:[
   {
   "_id": "5771ce2b421aa931d274f244",
   "createdAt": "2016-06-28T09:08:59.622Z",
   "desc": "一款类似豆瓣读书的APP,提供一个书籍查看、搜索、交流的平台,数据来自豆瓣(爬虫),后端LeanCloud。",
   "images": [
   "http://img.gank.io/0b7e425d-f61c-4eff-ae9c-8b5613020be9",
   "http://img.gank.io/c0cc0c8b-17b6-4321-bfdc-1cb0732edd4d",
   "http://img.gank.io/0203a555-edc1-4577-b83b-42a8a723dd87",
   "http://img.gank.io/8671a3f2-5546-4f0b-9d5c-538ad51aa8cf"
   ],
   "publishedAt": "2019-08-06T11:58:37.715Z",
   "source": "web",
   "type": "App",
   "url": "https://github.com/Blankeer/SoleBooks",
   "used": true,
   "who": "潇湘剑雨"
   }]

建两个 类,GankToday和GankBean.

class GankBean {
  String id;
  String createdAt;
  String desc;
  String publishedAt;
  String source;
  String type;
  String url;
  bool used;
  String who;
  List<String> images;

  GankBean.fromJson(Map<String, dynamic> json) {
    //print("item:$json");
    id = json['_id'];
    createdAt = json['createdAt'];
    desc = json['desc'];
    publishedAt = json['publishedAt'];
    source = json['source'];
    type = json['type'];
    url = json['url'];
    used = json['used'];
    desc = json['desc'];
    who = json['who'];
    images =
        json['images']?.map<String>((image) => image as String)?.toList() ?? [];
  }
}
class GankToday {
  bool error;
  List<String> category;
  Map<String, List<GankBean>> items = Map();

  List<GankBean> beans = [];

  GankToday(this.category);

  GankToday.fromJson(Map<String, dynamic> json) {
    error = json['error'];
    category = List<String>.from(json['category']);
    //print('json:' + category.toString());

    var results = json['results'];
    results.forEach((key, listVal) {
      if (key != '福利') {
        items[key] = _parseGankBeanFromJson(key, listVal);
      }
    });
    print("decode end");
  }

  List<GankBean> _parseGankBeanFromJson(key, listVal) {
    var list =
        listVal.map<GankBean>((item) => GankBean.fromJson(item)).toList();
    beans.addAll(list);
    return list;
  }

这种数据结构,用序列化的方式似乎不太可行,所以只能手动了. 其间参考了一下官方的应用, 简化了一点代码.

构建页面:

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

  @override
  _GankJsonListPageState createState() => new _GankJsonListPageState();
}

这都 是标准的;

class _GankJsonListPageState extends State<GankJsonListPage> {
ListView buildListView() => ListView.builder(
    itemCount: length,
    itemBuilder: (BuildContext context, int position) {
      return buildRow(position);
    });

Widget buildRow(int i) {
  var beans = gankToday.beans;
  //print('bean i:$i data:$beans');
  if (beans == null) {
    return Text("no items:");
  }
  var bean = beans[i];
  if (bean.images == null || bean.images.length < 1) {
    return GestureDetector(
      onTap: () {
        setState(() {
          detail(bean);
        });
      },
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
              padding: EdgeInsets.only(
                  left: 10.0, right: 10.0, top: 5.0, bottom: 5.0),
              child: Text("Title:${bean.publishedAt}")),
          Padding(
              padding: EdgeInsets.only(
                  left: 10.0, right: 10.0, top: 5.0, bottom: 5.0),
              child: Text("Title:${bean.desc}")),
        ],
      ),
    );
  } else {
    return GestureDetector(
      onTap: () {
        setState(() {
          detail(bean);
        });
      },
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
              padding: EdgeInsets.only(
                  left: 10.0, right: 10.0, top: 5.0, bottom: 5.0),
              child: Text("Title:${bean.publishedAt}")),
          Padding(
              padding: EdgeInsets.only(
                  left: 10.0, right: 10.0, top: 5.0, bottom: 5.0),
              child: Text("Url:${bean.images[0]}")),
          Padding(
            padding: EdgeInsets.only(left: 10.0, right: 10.0),
            child: Image(
              image: CachedNetworkImageProvider(bean.images[0]),
              //width: album.images.width.toDouble(),
              //height: album.images.height.toDouble(),
              fit: BoxFit.fitWidth,
            ),
          ),
        ],
      ),
    );
  }
} 
}

上面,分有图与无图的,先这么用, 后续可以按多个类型来处理,重构一下.

跳转到详情页:

void detail(GankBean gankBean) {
  Navigator.of(context).push(
    new MaterialPageRoute<void>(
      builder: (BuildContext context) {
        return new GankDetailPage(
          gankBean: gankBean,
        );
      },
    ),
  );
}
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: buildListView(),
  );
}

到这里widget就构建完成了.

到加载数据了:

GankToday gankToday = GankToday([]);
var length = 0;

@override
void initState() {
  super.initState();
  loadData();
}
loadData() async {
  String dataURL = "http://gank.io/api/today";
  http.Response response = await http.get(dataURL);
  setState(() {
    Map<String, dynamic> decodeJson = json.decode(response.body);
    gankToday = GankToday.fromJson(decodeJson);
    length = gankToday.items[gankToday.category[0]].length;
    print(
        "length:${gankToday.category}, content:${gankToday.items.length}");
  });
 
//如果你把json文件放在assets目录里,也是可以的,这样就调用下面这样的代码.
  /*loadAsset().then((value) {
    setState(() {
      var raw = json.decode(value);
      //it's a Map<>,translate to List:raw.map().toList()
      albums =
          new List<Album>.from(raw.map((i) => Album.fromJson(i)).toList());
      print(albums[0]);
    });
  });*/
}

然后在main里调用就可以了.

runApp(HomeTabsPage());
class HomeTabsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Home',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
        //primaryColor: Colors.white,
      ),
      home: new GankJsonListPage(),
    );
  }
}

到此,一个简单的列表就完成了.代码就是有点乱.到详情页的部分还没有添加.可以自行完成.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值