iT邦幫忙

2021 iThome 鐵人賽

DAY 23
0
Mobile Development

Flutter with GetX, loading*175%歷程 系列 第 23

[Day23] Flutter GetX with Dio (二)

  • 分享至 

  • xImage
  •  

承襲前一篇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


上一篇
[Day22] Flutter GetX with Dio (一)
下一篇
[Day24] Flutter with GetX Shimmer
系列文
Flutter with GetX, loading*175%歷程 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言