[Day23] Flutter GetX with Dio (二)

承袭前一篇Dio 这篇是接着发起request 这次范例是使用News API
response 回来把资料作後续处理

Data model
可以用这个工具把API的JSON格式档案贴上转成Model
这边先只列出比较外层的部分 全部请参考这里

class News {
  String status = "";
  int totalResults = -1;
  List<Articles> articles = [];

  News();

  News.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    totalResults = json['totalResults'];
    if (json['articles'] != null) {
      articles = [];
      json['articles'].forEach((v) {
        articles.add(new Articles.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['status'] = this.status;
    data['totalResults'] = this.totalResults;
    data['articles'] = this.articles.map((v) => v.toJson()).toList();
    return data;
  }
}

ApiService部分
apiKey可以替换成自己的

class ApiService {
  Future<News> getNews() async {
    var response = await HttpUtil().get(
        '/everything?q=tesla&from=2021-10-05&sortBy=publishedAt&apiKey=989e07f02f47475daa7020cb0498af8e');
    if (response is DioError) {
      print(response.response!.statusCode);
      return News();
    }
    return News.fromJson(response.data);
  }
}

接着来实际在页面呼叫
包含Widget, Controller, repository三个部分
关系分别是
Widget <-> Controller <-> repository <-> ApiService.

Widget部分
在等待API fetch data isLoading 完成前,
将会是转圈圈等待资料回来的状态, controller的dataList被assign资料後,
Widget部分由Obx立即响应渲染ListView.

class NewsPage extends GetView<NewsPageController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('NewsPage')),
      body: SafeArea(
        child: Obx(
          () => (controller.isLoading)
              ? Center(child: CircularProgressIndicator())
              : ListView.builder(
                  itemCount: controller.dataList.length,
                  itemBuilder: (_, index) {
                    final title = controller.dataList[index].title;
                    final content = controller.dataList[index].content;
                    return Card(
                      child: ListTile(
                        title: Text(title),
                        subtitle: Text(content),
                      ),
                    );
                  },
                ),
        ),
      ),
    );
  }
}

Controller部分
在onInit()时fetchAPI


class NewsPageController extends GetxController {
  NewsPageController({required this.repository});

  final NewsPageRepository repository;

  final _isLoading = true.obs;
  set isLoading(value) => this._isLoading.value = value;
  get isLoading => this._isLoading.value;

  final _dataList = <Articles>[].obs;
  get dataList => this._dataList.toList();

  @override
  void onInit() async {
    await fetchData();
    super.onInit();
  }

  fetchData() async {
    isLoading = true;
    final newsResult = await repository.getNews();
    _dataList.assignAll(newsResult.articles);
    isLoading = false;
  }
}

repository部分

abstract class NewsPageRepository {
  Future getNews();
}

class NewsPageRepositoryImpl implements NewsPageRepository {
  NewsPageRepositoryImpl();

  final apiService = ApiService();

  @override
  Future<News> getNews() async {
    return await apiService.getNews();
  }
}

最後效果如下
https://cdn-images-1.medium.com/max/800/1*Dd-Ca7nTwzl7C3gHS56W9Q.gif

本篇的GitHub source code

下一篇将为大家介绍Shimmer


<<:  Day 22 Odoo 动态domain

>>:  Day 23 - 将 Yacht Manager 後台储存资料提取後,送至前台渲染首页 Home 页面 (下) - 新闻图卡区 - ASP.NET Web Forms C#

网路是怎样连接的(七)TCP的交互(下)

思考重点 TCP如何确认对方收到消息? 讯息收发中的头部消息变化? 关闭连接操作? 核心知识 封包的...

TailwindCSS 从零开始 - 手机到桌上萤幕,所有的元素都能自适应

跟 Bootstrap 一样也是手机优先的响应式断点设计,官方文件也提供尺寸对照: 让前端在开发轻...

粗略的HDR理解

正如同Gamma校正一样,只要是跟电脑图像相关的,一定会听过HDR这个词,今天跟昨天(Day27)一...

[Day 2] 超级简单介绍Vue.js

今天是第二天!!我有记得发文,好耶~~那就直接来看看今天的内容吧~!(好突然) 个人认为在学习新技术...

追求JS小姊姊系列 Day6 -- 郑列展现的工具力(上)

前情提要 郑列疑似烙下狠话,正要展现工具实力?! 郑列:我说啊,你知道身为工具人要会做哪些事吗? 答...