从JSON加载内容,缓存它并在Flutter

时间:2018-06-01 07:51:58

标签: dart flutter

我是移动应用程序开发的先驱者。我一直试图操纵我的代码来完成从Rest API检索到的JSON数据的一些事情。

我想要的是什么:

  • 缓存检索到的内容,以便在用户打开应用时不必调用CircularProgressIndicator()
  • 大约30秒后,内容将刷新以从Rest API获取新的更新数据,用户也可以手动刷新。

以下是我的代码到目前为止(它不会在30秒后自动刷新,当用户触发RefreshIndicator()时,它会刷新并将新获取的数据放在下面而不删除旧数据。)

请帮忙

import 'dart:convert';
import 'dart:io';
import 'dart:async';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:timeago/timeago.dart';
import 'package:flutter/material.dart';
import 'about.dart';
import 'post.dart';
import 'post_details.dart';
import 'strings.dart';
import 'package:http/http.dart' as http;

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

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

class _MyHomePageState extends State<MyHomePage> {
  bool _isRequestSent = false;
  bool _isRequestFailed = false;
  var refreshKey = GlobalKey<RefreshIndicatorState>();
  List<Post> postList = [];

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

  Future<Null> refreshList() async {
    refreshKey.currentState?.show(atTop: false);
    await Future.delayed(Duration(seconds: 2));

    setState(() {
      _isRequestSent = true;
    });

    return null;
  }

  @override
  Widget build(BuildContext context)  {
    // This method is rerun every time setState is called.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.

    if (!_isRequestSent) {
      sendRequest();
    }
    return Scaffold(
      drawer: Drawer(
          child: ListView(
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text('Gossipper'),
                decoration: BoxDecoration(color: Colors.white),
              ),
              ListTile(
                title: Text('Home'),
                onTap: () {
                  Navigator.push(context,
                  MaterialPageRoute(
                      builder: (BuildContext context) => AboutUs()
                      ),
                  );
                },
              ),
              ListTile(
                title: Text('Forum'),
                onTap: () {

                },
              ),

            ],
          ),
      ),
      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),
        backgroundColor: Colors.green,
        centerTitle: true,
      ),
      body: new Container(
        alignment: Alignment.center,
        child: !_isRequestSent
        //  Request has not been sent, let's show a progress indicator
            ? new CircularProgressIndicator(backgroundColor: Colors.green,)

        // Request has been sent but did it fail?
            : _isRequestFailed
        // Yes, it has failed. Show a retry UI
            ? _showRetryUI()
        // No it didn't fail. Show the data
            : new Container(
          child: RefreshIndicator(
            key: refreshKey,
            color: Colors.green,
            child: ListView.builder(
              itemCount: postList.length,
              scrollDirection: Axis.vertical,
              padding: EdgeInsets.all(8.0),
              itemBuilder: (BuildContext context, int index) {
                return _getPostWidgets(index);
              }),
            onRefresh: refreshList,
          ),
        ),
      ),
    );
  }

  void sendRequest() async {
    String url =
        "https://api.gossipper.com/posts";
    try {
      http.Response response = await http.get(url);
      // Did request succeeded?
      if (response.statusCode == HttpStatus.OK) {
        // We're expecting a Json object as the result
        Map decode = json.decode(response.body);
        parseResponse(decode);
      } else {
        print(response.statusCode);
        handleRequestError();
      }
    } catch (e) {
      print(e);
      handleRequestError();
    }
  }

  Widget _getPostWidgets(int index) {
    var post = postList[index];
    return new GestureDetector(
      onTap: () {
        openDetailsUI(post);
      },
      child: new Container(
        margin: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
        child: new Card(
          elevation: 3.0,
          child: new Row(
            children: <Widget>[
              new Container(
                width: 150.0,
                child: new CachedNetworkImage(
                  imageUrl: post.thumbUrl,
                  fit: BoxFit.cover,
                  placeholder: new Icon(
                    Icons.panorama,
                    color: Colors.grey,
                    size: 120.0,
                  ),
                ),
              ),
              new Expanded(
                  child: new Container(
                    margin: new EdgeInsets.all(10.0),
                    child: new Text(
                      post.title,
                      style: new TextStyle(color: Colors.black, fontSize: 18.0),
                    ),
                  )),

            ],
          ),
        ),
      ),
    );
  }

  void parseResponse(Map response) {
    List results = response["results"];
    for (var jsonObject in results) {
      var post = Post.getPostFrmJSONPost(jsonObject);
      postList.add(post);
      print(post);
    }
    setState(() => _isRequestSent = true);
  }

  void handleRequestError() {
    setState(() {
      _isRequestSent = true;
      _isRequestFailed = true;
    });
  }

  Widget _showRetryUI() {
    return new Container(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new Text(
            Strings.requestFailed,
            style: new TextStyle(fontSize: 16.0),
          ),
          new Padding(
            padding: new EdgeInsets.only(top: 10.0),
            child: new RaisedButton(
              onPressed: retryRequest,
              child: new Text(
                Strings.retry,
                style: new TextStyle(color: Colors.white),
              ),
              color: Theme.of(context).accentColor,
              splashColor: Colors.deepOrangeAccent,
            ),
          )
        ],
      ),
    );
  }

  void retryRequest() {
    setState(() {
      // Let's just reset the fields.
      _isRequestSent = false;
      _isRequestFailed = false;
    });
  }

  openDetailsUI(Post post) {
    Navigator.push(
        context,
        new MaterialPageRoute(
            builder: (BuildContext context) => new PostDetails(post)));
  }
}

0 个答案:

没有答案