Jonny Borges
Committed by GitHub

Merge branch 'master' into master

@@ -96,7 +96,7 @@ Get.put<S>( @@ -96,7 +96,7 @@ Get.put<S>(
96 bool overrideAbstract = false, 96 bool overrideAbstract = false,
97 97
98 // optional: allows you to create the dependency using function instead of the dependency itself. 98 // optional: allows you to create the dependency using function instead of the dependency itself.
99 - FcBuilderFunc<S> builder, 99 + InstanceBuilderCallback<S> builder,
100 ) 100 )
101 ``` 101 ```
102 102
@@ -106,7 +106,7 @@ Get.put<S>( @@ -106,7 +106,7 @@ Get.put<S>(
106 Get.lazyPut<S>( 106 Get.lazyPut<S>(
107 // mandatory: a method that will be executed when your class is called for the first time 107 // mandatory: a method that will be executed when your class is called for the first time
108 // Example: Get.lazyPut<Controller>( () => Controller() ) 108 // Example: Get.lazyPut<Controller>( () => Controller() )
109 - FcBuilderFunc builder, 109 + InstanceBuilderCallback builder,
110 110
111 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 111 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
112 // must be unique 112 // must be unique
@@ -128,7 +128,7 @@ Get.putAsync<S>( @@ -128,7 +128,7 @@ Get.putAsync<S>(
128 128
129 // mandatory: an async method that will be executed to instantiate your class 129 // mandatory: an async method that will be executed to instantiate your class
130 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() ) 130 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
131 - FcBuilderFuncAsync<S> builder, 131 + AsyncInstanceBuilderCallback<S> builder,
132 132
133 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 133 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
134 // must be unique 134 // must be unique
@@ -99,7 +99,7 @@ Get.put<S>( @@ -99,7 +99,7 @@ Get.put<S>(
99 bool overrideAbstract = false, 99 bool overrideAbstract = false,
100 100
101 // optional: allows you to create the dependency using function instead of the dependency itself. 101 // optional: allows you to create the dependency using function instead of the dependency itself.
102 - FcBuilderFunc<S> builder, 102 + InstanceBuilderCallback<S> builder,
103 ) 103 )
104 ``` 104 ```
105 105
@@ -109,7 +109,7 @@ Get.put<S>( @@ -109,7 +109,7 @@ Get.put<S>(
109 Get.lazyPut<S>( 109 Get.lazyPut<S>(
110 // mandatory: a method that will be executed when your class is called for the first time 110 // mandatory: a method that will be executed when your class is called for the first time
111 // Example: Get.lazyPut<Controller>( () => Controller() ) 111 // Example: Get.lazyPut<Controller>( () => Controller() )
112 - FcBuilderFunc builder, 112 + InstanceBuilderCallback builder,
113 113
114 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 114 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
115 // must be unique 115 // must be unique
@@ -131,7 +131,7 @@ Get.putAsync<S>( @@ -131,7 +131,7 @@ Get.putAsync<S>(
131 131
132 // mandatory: an async method that will be executed to instantiate your class 132 // mandatory: an async method that will be executed to instantiate your class
133 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() ) 133 // Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
134 - FcBuilderFuncAsync<S> builder, 134 + AsyncInstanceBuilderCallback<S> builder,
135 135
136 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class 136 // optional: same as Get.put(), it is used for when you want multiple different instance of a same class
137 // must be unique 137 // must be unique
@@ -96,7 +96,7 @@ Get.put<S>( @@ -96,7 +96,7 @@ Get.put<S>(
96 bool permanent = false, 96 bool permanent = false,
97 97
98 // opcional: permite criar a dependência usando uma função em vez da dependênia em si 98 // opcional: permite criar a dependência usando uma função em vez da dependênia em si
99 - FcBuilderFunc<S> builder, 99 + InstanceBuilderCallback<S> builder,
100 ) 100 )
101 ``` 101 ```
102 102
@@ -106,7 +106,7 @@ Get.put<S>( @@ -106,7 +106,7 @@ Get.put<S>(
106 Get.lazyPut<S>( 106 Get.lazyPut<S>(
107 // obrigatório: um método que vai ser executado quando sua classe é chamada pela primeira vez 107 // obrigatório: um método que vai ser executado quando sua classe é chamada pela primeira vez
108 // Exemplo: "Get.lazyPut<Controller>( () => Controller() 108 // Exemplo: "Get.lazyPut<Controller>( () => Controller()
109 - FcBuilderFunc builder, 109 + InstanceBuilderCallback builder,
110 110
111 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe 111 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe
112 // precisa ser uma string única 112 // precisa ser uma string única
@@ -127,7 +127,7 @@ Get.lazyPut<S>( @@ -127,7 +127,7 @@ Get.lazyPut<S>(
127 Get.putAsync<S>( 127 Get.putAsync<S>(
128 // Obrigatório: um método assíncrono que vai ser executado para instanciar sua classe 128 // Obrigatório: um método assíncrono que vai ser executado para instanciar sua classe
129 // Exemplo: Get.putAsyn<YourAsyncClass>( () async => await YourAsyncClass() ) 129 // Exemplo: Get.putAsyn<YourAsyncClass>( () async => await YourAsyncClass() )
130 - FcBuilderFuncAsync<S> builder, 130 + AsyncInstanceBuilderCallback<S> builder,
131 131
132 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe 132 // opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe
133 // precisa ser uma string única 133 // precisa ser uma string única
@@ -144,7 +144,7 @@ Get.putAsync<S>( @@ -144,7 +144,7 @@ Get.putAsync<S>(
144 Get.create<S>( 144 Get.create<S>(
145 // Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado 145 // Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado
146 // Exemplo: Get.create<YourClass>(() => YourClass()) 146 // Exemplo: Get.create<YourClass>(() => YourClass())
147 - FcBuilderFunc<S> builder, 147 + InstanceBuilderCallback<S> builder,
148 148
149 // opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe. 149 // opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe.
150 // Útil caso você tenha uma lista em que cada item precise de um controller próprio 150 // Útil caso você tenha uma lista em que cada item precise de um controller próprio
@@ -170,7 +170,7 @@ A diferença fundamental entre `permanent` e `fenix` está em como você quer ar @@ -170,7 +170,7 @@ A diferença fundamental entre `permanent` e `fenix` está em como você quer ar
170 170
171 Prosseguindo com as diferenças entre os métodos: 171 Prosseguindo com as diferenças entre os métodos:
172 172
173 -- Get.put e Get.putAsync seguem a mesma ordem de criação, com a diferença que o Async opta por aplicar um método assíncrono: Esses dois métodos criam e já inicializam a instância. Esta é inserida diretamente na memória, através do método interno `insert` com os parâmetros `permanent: false` e `isSingleton: true` (esse parâmetro `isSingleton` serve apenas para dizer se é para utilizar a dependência colocada em `dependency`, ou se é para usar a dependência colocada no `FcBuilderFunc`). Depois disso, é chamado o `Get.find` que imediatamente inicializa as instâncias que estão na memória. 173 +- Get.put e Get.putAsync seguem a mesma ordem de criação, com a diferença que o Async opta por aplicar um método assíncrono: Esses dois métodos criam e já inicializam a instância. Esta é inserida diretamente na memória, através do método interno `insert` com os parâmetros `permanent: false` e `isSingleton: true` (esse parâmetro `isSingleton` serve apenas para dizer se é para utilizar a dependência colocada em `dependency`, ou se é para usar a dependência colocada no `InstanceBuilderCallback`). Depois disso, é chamado o `Get.find` que imediatamente inicializa as instâncias que estão na memória.
174 174
175 - Get.create: Como o nome indica, você vai "criar" a sua dependência! Similar ao `Get.put`, ela também chama o método interno `insert` para instanciamento. Contudo, `permanent` e `isSingleton` passam a ser `true` e `false` (Como estamos "criando" a nossa dependência, não tem como ela ser um Singleton de algo, logo, `false`). E por ser `permanent: true`, temos por padrão o benefício de não se perder entre telas! Além disso, não é chamado o `Get.find`, logo ela fica esperando ser chamada para ser usada. Ele é criado dessa forma para aproveitar o uso do parâmetro `permanent`, já que, vale ressaltar, o Get.create foi criado com o objetivo de criar instâncias não compartilhadas, mas que não se perdem, como por exemplo um botão em um listView, que você quer uma instância única para aquela lista - por conta disso, o Get.create deve ser usado em conjunto com o GetWidget. 175 - Get.create: Como o nome indica, você vai "criar" a sua dependência! Similar ao `Get.put`, ela também chama o método interno `insert` para instanciamento. Contudo, `permanent` e `isSingleton` passam a ser `true` e `false` (Como estamos "criando" a nossa dependência, não tem como ela ser um Singleton de algo, logo, `false`). E por ser `permanent: true`, temos por padrão o benefício de não se perder entre telas! Além disso, não é chamado o `Get.find`, logo ela fica esperando ser chamada para ser usada. Ele é criado dessa forma para aproveitar o uso do parâmetro `permanent`, já que, vale ressaltar, o Get.create foi criado com o objetivo de criar instâncias não compartilhadas, mas que não se perdem, como por exemplo um botão em um listView, que você quer uma instância única para aquela lista - por conta disso, o Get.create deve ser usado em conjunto com o GetWidget.
176 176
1 -import 'package:get/get.dart';  
2 -import '../data/home_model.dart';  
3 -import '../data/home_repository.dart';  
4 -  
5 -class HomeController extends GetxController {  
6 - HomeController({this.homeRepository});  
7 - final HomeRepository homeRepository;  
8 -  
9 - Rx<ApiModel> data = Rx<ApiModel>();  
10 -  
11 - @override  
12 - void onInit() => fetchDataFromApi();  
13 -  
14 - void fetchDataFromApi() async {  
15 - data.value = await homeRepository.getData();  
16 - if (data.value == null) {  
17 - Get.snackbar("Error", "Can't connect to server");  
18 - }  
19 - }  
20 -}  
1 -import 'package:dio/dio.dart';  
2 -import 'package:flutter/foundation.dart';  
3 -import 'home_model.dart';  
4 -  
5 -abstract class IHomeProvider {  
6 - Future<ApiModel> get();  
7 - Future<ApiModel> post(Map<String, dynamic> data);  
8 - Future<ApiModel> put(Map<String, dynamic> data);  
9 - Future<ApiModel> delete(int id);  
10 -}  
11 -  
12 -class HomeProvider implements IHomeProvider {  
13 - final Dio dio;  
14 -  
15 - HomeProvider({@required this.dio});  
16 -  
17 - Future<ApiModel> get() async {  
18 - try {  
19 - final response = await dio.get("https://api.covid19api.com/summary");  
20 - return ApiModel.fromJson(response.data);  
21 - } catch (e) {  
22 - print(e.toString());  
23 - return null;  
24 - }  
25 - }  
26 -  
27 - @override  
28 - Future<ApiModel> post(Map<String, dynamic> data) {  
29 - throw UnimplementedError();  
30 - }  
31 -  
32 - @override  
33 - Future<ApiModel> put(Map<String, dynamic> data) {  
34 - throw UnimplementedError();  
35 - }  
36 -  
37 - @override  
38 - Future<ApiModel> delete(int id) {  
39 - throw UnimplementedError();  
40 - }  
41 -}  
1 -import 'home_model.dart';  
2 -import 'home_provider.dart';  
3 -  
4 -class HomeRepository {  
5 - HomeRepository({this.homeProvider});  
6 - final HomeProvider homeProvider;  
7 -  
8 - Future<ApiModel> getData() async {  
9 - return homeProvider.get();  
10 - }  
11 -}  
1 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 -import 'package:get_state/home/bindings/home_binding.dart';  
4 -import 'package:get_state/home/views/country_view.dart';  
5 -import 'home/views/details_view.dart';  
6 -import 'home/views/home_view.dart'; 3 +import 'package:get_state/routes/app_pages.dart';
  4 +import 'shared/logger/logger_utils.dart';
7 5
8 void main() { 6 void main() {
9 - runApp(  
10 - GetMaterialApp( 7 + runApp(MyApp());
  8 +}
  9 +
  10 +class MyApp extends StatelessWidget {
  11 + const MyApp({Key key}) : super(key: key);
  12 +
  13 + @override
  14 + Widget build(BuildContext context) {
  15 + return GetMaterialApp(
11 debugShowCheckedModeBanner: false, 16 debugShowCheckedModeBanner: false,
12 - initialRoute: '/',  
13 enableLog: true, 17 enableLog: true,
14 - // logWriterCallback: localLogWriter,  
15 - getPages: [  
16 - GetPage(name: '/', page: () => HomePage(), binding: HomeBinding()),  
17 - GetPage(name: '/country', page: () => CountryPage()),  
18 - GetPage(name: '/details', page: () => DetailsPage()),  
19 - ],  
20 - ), 18 + logWriterCallback: Logger.write,
  19 + initialRoute: AppPages.INITIAL,
  20 + getPages: AppPages.routes,
21 ); 21 );
22 -}  
23 -  
24 -// Sample of abstract logging function  
25 -void localLogWriter(String text, {bool isError = false}) {  
26 - print('** ' + text + ' [' + isError.toString() + ']'); 22 + }
27 } 23 }
1 import 'package:dio/dio.dart'; 1 import 'package:dio/dio.dart';
2 import 'package:get/get.dart'; 2 import 'package:get/get.dart';
3 -import '../controllers/home_controller.dart';  
4 -import '../data/home_provider.dart'; 3 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  4 +import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
5 import '../data/home_repository.dart'; 5 import '../data/home_repository.dart';
6 6
7 class HomeBinding extends Bindings { 7 class HomeBinding extends Bindings {
8 @override 8 @override
9 void dependencies() { 9 void dependencies() {
10 - Get.lazyPut<HomeController>(() {  
11 - Get.put(Dio());  
12 - Get.put(HomeProvider(dio: Get.find()));  
13 - Get.put(HomeRepository(homeProvider: Get.find()));  
14 - return HomeController(homeRepository: Get.find());  
15 - }); 10 + Get.lazyPut(() => Dio());
  11 + Get.lazyPut<IHomeRepository>(() => HomeRepository(dio: Get.find()));
  12 + Get.lazyPut(() => HomeController(homeRepository: Get.find()));
16 } 13 }
17 } 14 }
  1 +import 'package:dio/dio.dart';
  2 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  3 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  4 +
  5 +class HomeRepository implements IHomeRepository {
  6 + HomeRepository({this.dio});
  7 + final Dio dio;
  8 +
  9 + @override
  10 + Future<CasesModel> getCases() async {
  11 + try {
  12 + final response = await dio.get("https://api.covid19api.com/summary");
  13 + return CasesModel.fromJson(response.data);
  14 + } catch (e) {
  15 + print(e.toString());
  16 + return Future.error(e.toString());
  17 + }
  18 + }
  19 +}
  1 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  2 +
  3 +abstract class IHomeRepository {
  4 + Future<CasesModel> getCases();
  5 +}
1 // To parse this JSON data, do 1 // To parse this JSON data, do
2 // 2 //
3 -// final apiModel = apiModelFromJson(jsonString); 3 +// final CasesModel = CasesModelFromJson(jsonString);
4 4
5 import 'dart:convert'; 5 import 'dart:convert';
6 6
7 -class ApiModel { 7 +class CasesModel {
8 final Global global; 8 final Global global;
9 final List<Country> countries; 9 final List<Country> countries;
10 final String date; 10 final String date;
11 11
12 - ApiModel({ 12 + CasesModel({
13 this.global, 13 this.global,
14 this.countries, 14 this.countries,
15 this.date, 15 this.date,
16 }); 16 });
17 17
18 - factory ApiModel.fromRawJson(String str) =>  
19 - ApiModel.fromJson(json.decode(str)); 18 + factory CasesModel.fromRawJson(String str) =>
  19 + CasesModel.fromJson(json.decode(str));
20 20
21 String toRawJson() => json.encode(toJson()); 21 String toRawJson() => json.encode(toJson());
22 22
23 - factory ApiModel.fromJson(Map<String, dynamic> json) => ApiModel( 23 + factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel(
24 global: json["Global"] == null ? null : Global.fromJson(json["Global"]), 24 global: json["Global"] == null ? null : Global.fromJson(json["Global"]),
25 countries: json["Countries"] == null 25 countries: json["Countries"] == null
26 ? null 26 ? null
  1 +import 'package:get/get.dart';
  2 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  3 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  4 +
  5 +enum Status { loading, success, error }
  6 +
  7 +class HomeController extends GetxController {
  8 + HomeController({this.homeRepository});
  9 +
  10 + /// inject repo abstraction dependency
  11 + final IHomeRepository homeRepository;
  12 +
  13 + /// create a reactive status from request with initial value = loading
  14 + final status = Status.loading.obs;
  15 +
  16 + /// create a reactive CasesModel. CasesModel().obs has same result
  17 + final cases = Rx<CasesModel>();
  18 +
  19 + /// When the controller is initialized, make the http request
  20 + @override
  21 + void onInit() => fetchDataFromApi();
  22 +
  23 + /// fetch cases from Api
  24 + Future<void> fetchDataFromApi() async {
  25 + /// When the repository returns the value, change the status to success, and fill in "cases"
  26 + return homeRepository.getCases().then(
  27 + (data) {
  28 + cases(data);
  29 + status(Status.success);
  30 + },
  31 +
  32 + /// In case of error, print the error and change the status to Status.error
  33 + onError: (err) {
  34 + print("$err");
  35 + return status(Status.error);
  36 + },
  37 + );
  38 + }
  39 +}
1 import 'dart:ui'; 1 import 'dart:ui';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 -import 'package:get_state/home/controllers/home_controller.dart';  
4 -import 'package:get_state/home/data/home_model.dart';  
5 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
  4 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  5 +import '../controllers/home_controller.dart';
6 6
7 -class CountryPage extends GetWidget<HomeController> { 7 +class CountryView extends GetWidget<HomeController> {
8 @override 8 @override
9 Widget build(BuildContext context) { 9 Widget build(BuildContext context) {
10 return Container( 10 return Container(
@@ -28,9 +28,9 @@ class CountryPage extends GetWidget<HomeController> { @@ -28,9 +28,9 @@ class CountryPage extends GetWidget<HomeController> {
28 ), 28 ),
29 body: Center( 29 body: Center(
30 child: ListView.builder( 30 child: ListView.builder(
31 - itemCount: controller.data.value.countries.length, 31 + itemCount: controller.cases.value.countries.length,
32 itemBuilder: (context, index) { 32 itemBuilder: (context, index) {
33 - Country country = controller.data.value.countries[index]; 33 + Country country = controller.cases.value.countries[index];
34 return ListTile( 34 return ListTile(
35 onTap: () { 35 onTap: () {
36 Get.toNamed('/details', arguments: country); 36 Get.toNamed('/details', arguments: country);
1 import 'dart:ui'; 1 import 'dart:ui';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
4 -import 'package:get_state/home/data/home_model.dart'; 4 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
5 5
6 -class DetailsPage extends StatelessWidget { 6 +class DetailsView extends StatelessWidget {
7 @override 7 @override
8 Widget build(BuildContext context) { 8 Widget build(BuildContext context) {
9 Country country = Get.arguments; 9 Country country = Get.arguments;
1 import 'dart:ui'; 1 import 'dart:ui';
2 import 'package:flutter/material.dart'; 2 import 'package:flutter/material.dart';
3 import 'package:get/get.dart'; 3 import 'package:get/get.dart';
4 -import 'package:get_state/home/controllers/home_controller.dart'; 4 +import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
5 5
6 -class HomePage extends GetWidget<HomeController> { 6 +class HomeView extends GetView<HomeController> {
7 @override 7 @override
8 Widget build(BuildContext context) { 8 Widget build(BuildContext context) {
9 return Container( 9 return Container(
@@ -23,9 +23,12 @@ class HomePage extends GetWidget<HomeController> { @@ -23,9 +23,12 @@ class HomePage extends GetWidget<HomeController> {
23 centerTitle: true, 23 centerTitle: true,
24 ), 24 ),
25 body: Center( 25 body: Center(
26 - child: Obx(() => (controller.data() == null)  
27 - ? CircularProgressIndicator()  
28 - : Column( 26 + child: Obx(
  27 + () {
  28 + Status status = controller.status.value;
  29 + if (status == Status.loading) return CircularProgressIndicator();
  30 + if (status == Status.error) return Text('Error on connection :(');
  31 + return Column(
29 mainAxisAlignment: MainAxisAlignment.center, 32 mainAxisAlignment: MainAxisAlignment.center,
30 children: [ 33 children: [
31 SizedBox( 34 SizedBox(
@@ -38,9 +41,8 @@ class HomePage extends GetWidget<HomeController> { @@ -38,9 +41,8 @@ class HomePage extends GetWidget<HomeController> {
38 ), 41 ),
39 ), 42 ),
40 Text( 43 Text(
41 - '${controller.data.value.global.totalConfirmed}',  
42 - style:  
43 - TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 44 + '${controller.cases.value.global.totalConfirmed}',
  45 + style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
44 ), 46 ),
45 SizedBox( 47 SizedBox(
46 height: 10, 48 height: 10,
@@ -52,9 +54,8 @@ class HomePage extends GetWidget<HomeController> { @@ -52,9 +54,8 @@ class HomePage extends GetWidget<HomeController> {
52 ), 54 ),
53 ), 55 ),
54 Text( 56 Text(
55 - '${controller.data.value.global.totalDeaths}',  
56 - style:  
57 - TextStyle(fontSize: 45, fontWeight: FontWeight.bold), 57 + '${controller.cases.value.global.totalDeaths}',
  58 + style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
58 ), 59 ),
59 SizedBox( 60 SizedBox(
60 height: 10, 61 height: 10,
@@ -74,7 +75,9 @@ class HomePage extends GetWidget<HomeController> { @@ -74,7 +75,9 @@ class HomePage extends GetWidget<HomeController> {
74 ), 75 ),
75 ) 76 )
76 ], 77 ],
77 - )), 78 + );
  79 + },
  80 + ),
78 ), 81 ),
79 ), 82 ),
80 ); 83 );
  1 +import 'package:get/get.dart';
  2 +import 'package:get_state/pages/home/bindings/home_binding.dart';
  3 +import 'package:get_state/pages/home/presentation/views/country_view.dart';
  4 +import 'package:get_state/pages/home/presentation/views/details_view.dart';
  5 +import 'package:get_state/pages/home/presentation/views/home_view.dart';
  6 +
  7 +part 'app_routes.dart';
  8 +
  9 +class AppPages {
  10 + static const INITIAL = Routes.HOME;
  11 +
  12 + static final routes = [
  13 + GetPage(
  14 + name: Routes.HOME,
  15 + page: () => HomeView(),
  16 + binding: HomeBinding(),
  17 + ),
  18 + GetPage(
  19 + name: Routes.COUNTRY,
  20 + page: () => CountryView(),
  21 + ),
  22 + GetPage(
  23 + name: Routes.DETAILS,
  24 + page: () => DetailsView(),
  25 + ),
  26 + ];
  27 +}
  1 +part of 'app_pages.dart';
  2 +
  3 +abstract class Routes{
  4 +
  5 + static const HOME = '/home';
  6 + static const COUNTRY = '/country';
  7 + static const DETAILS = '/details';
  8 +}
  1 +class Logger {
  2 + // Sample of abstract logging function
  3 + static void write(String text, {bool isError = false}) {
  4 + print('** ' + text + ' [' + isError.toString() + ']');
  5 + }
  6 +}
  1 +import 'dart:math';
  2 +import 'package:flutter_test/flutter_test.dart';
  3 +import 'package:get/get.dart';
  4 +import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
  5 +import 'package:get_state/pages/home/domain/entity/cases_model.dart';
  6 +import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
  7 +import 'package:matcher/matcher.dart';
  8 +
  9 +class MockReposity implements IHomeRepository {
  10 + @override
  11 + Future<CasesModel> getCases() async {
  12 + await Future.delayed(Duration(milliseconds: 100));
  13 + return Random().nextBool()
  14 + ? CasesModel(
  15 + global: Global(totalDeaths: 100, totalConfirmed: 200),
  16 + )
  17 + : Future.error('error');
  18 + }
  19 +}
  20 +
  21 +void main() {
  22 + final binding = BindingsBuilder(() {
  23 + Get.lazyPut<IHomeRepository>(() => MockReposity());
  24 + Get.lazyPut<HomeController>(
  25 + () => HomeController(homeRepository: Get.find()));
  26 + });
  27 +
  28 + test('Test Binding', () {
  29 + expect(Get.isPrepared<HomeController>(), false);
  30 + expect(Get.isPrepared<IHomeRepository>(), false);
  31 +
  32 + /// test you Binding class with BindingsBuilder
  33 + binding.builder();
  34 +
  35 + expect(Get.isPrepared<HomeController>(), true);
  36 + expect(Get.isPrepared<IHomeRepository>(), true);
  37 +
  38 + Get.reset();
  39 + });
  40 + test('Test Controller', () async {
  41 + /// Controller can't be on memory
  42 + expect(() => Get.find<HomeController>(), throwsA(TypeMatcher<String>()));
  43 +
  44 + /// build Binding
  45 + binding.builder();
  46 +
  47 + /// recover your controller
  48 + HomeController controller = Get.find();
  49 +
  50 + /// check if onInit was called
  51 + expect(controller.initialized, true);
  52 +
  53 + /// check initial Status
  54 + expect(controller.status.value, Status.loading);
  55 +
  56 + /// await time request
  57 + await Future.delayed(Duration(milliseconds: 100));
  58 +
  59 + if (controller.status.value == Status.error) {
  60 + expect(controller.cases.value, null);
  61 + }
  62 +
  63 + if (controller.status.value == Status.success) {
  64 + expect(controller.cases.value.global.totalDeaths, 100);
  65 + expect(controller.cases.value.global.totalConfirmed, 200);
  66 + }
  67 + });
  68 +}
1 -// // This is a basic Flutter widget test.  
2 -// //  
3 -// // To perform an interaction with a widget in your test, use the WidgetTester  
4 -// // utility that Flutter provides. For example, you can send tap and scroll  
5 -// // gestures. You can also use WidgetTester to find child widgets in the widget  
6 -// // tree, read text, and verify that the values of widget properties are correct.  
7 -  
8 -// import 'package:flutter/material.dart';  
9 -// import 'package:flutter_test/flutter_test.dart';  
10 -  
11 -// import 'package:get_state/main.dart';  
12 -  
13 -// void main() {  
14 -// testWidgets('Counter increments smoke test', (WidgetTester tester) async {  
15 -// // Build our app and trigger a frame.  
16 -// await tester.pumpWidget(MyApp());  
17 -  
18 -// // Verify that our counter starts at 0.  
19 -// expect(find.text('0'), findsOneWidget);  
20 -// expect(find.text('1'), findsNothing);  
21 -  
22 -// // Tap the '+' icon and trigger a frame.  
23 -// await tester.tap(find.byIcon(Icons.add));  
24 -// await tester.pump();  
25 -  
26 -// // Verify that our counter has incremented.  
27 -// expect(find.text('0'), findsNothing);  
28 -// expect(find.text('1'), findsOneWidget);  
29 -// });  
30 -// }  
@@ -91,4 +91,6 @@ extension Inst on GetInterface { @@ -91,4 +91,6 @@ extension Inst on GetInterface {
91 /// Check if a Class Instance<[S]> (or [tag]) is registered in memory. 91 /// Check if a Class Instance<[S]> (or [tag]) is registered in memory.
92 /// - [tag] optional, if you use a [tag] to register the Instance. 92 /// - [tag] optional, if you use a [tag] to register the Instance.
93 bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag); 93 bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag);
  94 +
  95 + bool isPrepared<S>({String tag}) => GetInstance().isPrepared<S>(tag: tag);
94 } 96 }
@@ -209,6 +209,7 @@ class GetInstance { @@ -209,6 +209,7 @@ class GetInstance {
209 S find<S>({String tag}) { 209 S find<S>({String tag}) {
210 String key = _getKey(S, tag); 210 String key = _getKey(S, tag);
211 if (isRegistered<S>(tag: tag)) { 211 if (isRegistered<S>(tag: tag)) {
  212 +
212 if (_singl[key] == null) { 213 if (_singl[key] == null) {
213 if (tag == null) { 214 if (tag == null) {
214 throw 'Class "$S" is not register'; 215 throw 'Class "$S" is not register';
@@ -363,6 +364,5 @@ class _InstanceBuilderFactory<S> { @@ -363,6 +364,5 @@ class _InstanceBuilderFactory<S> {
363 class _Lazy { 364 class _Lazy {
364 bool fenix; 365 bool fenix;
365 InstanceBuilderCallback builder; 366 InstanceBuilderCallback builder;
366 -  
367 _Lazy(this.builder, this.fenix); 367 _Lazy(this.builder, this.fenix);
368 } 368 }
@@ -730,7 +730,7 @@ extension GetNavigation on GetInterface { @@ -730,7 +730,7 @@ extension GetNavigation on GetInterface {
730 Text( 730 Text(
731 title, 731 title,
732 style: TextStyle( 732 style: TextStyle(
733 - color: colorText ?? theme.iconTheme.color, 733 + color: colorText ?? Colors.black,
734 fontWeight: FontWeight.w800, 734 fontWeight: FontWeight.w800,
735 fontSize: 16), 735 fontSize: 16),
736 ), 736 ),
@@ -738,7 +738,7 @@ extension GetNavigation on GetInterface { @@ -738,7 +738,7 @@ extension GetNavigation on GetInterface {
738 Text( 738 Text(
739 message, 739 message,
740 style: TextStyle( 740 style: TextStyle(
741 - color: colorText ?? theme.iconTheme.color, 741 + color: colorText ?? Colors.black,
742 fontWeight: FontWeight.w300, 742 fontWeight: FontWeight.w300,
743 fontSize: 14), 743 fontSize: 14),
744 ), 744 ),
@@ -19,7 +19,7 @@ abstract class Bindings { @@ -19,7 +19,7 @@ abstract class Bindings {
19 /// ```` 19 /// ````
20 class BindingsBuilder extends Bindings { 20 class BindingsBuilder extends Bindings {
21 /// Register your dependencies in the [builder] callback. 21 /// Register your dependencies in the [builder] callback.
22 - final Function() builder; 22 + final void Function() builder;
23 23
24 BindingsBuilder(this.builder); 24 BindingsBuilder(this.builder);
25 25
@@ -44,9 +44,13 @@ abstract class DisposableInterface { @@ -44,9 +44,13 @@ abstract class DisposableInterface {
44 /// It uses an internal "callable" type, to avoid any @overrides in subclases. 44 /// It uses an internal "callable" type, to avoid any @overrides in subclases.
45 /// This method should be internal and is required to define the lifetime cycle 45 /// This method should be internal and is required to define the lifetime cycle
46 /// of the subclass. 46 /// of the subclass.
47 - ///  
48 final onStart = _InternalFinalCallback<void>(); 47 final onStart = _InternalFinalCallback<void>();
49 48
  49 + bool _initialized = false;
  50 +
  51 + /// Checks whether the controller has already been initialized.
  52 + bool get initialized => _initialized;
  53 +
50 DisposableInterface() { 54 DisposableInterface() {
51 onStart.callback = _onStart; 55 onStart.callback = _onStart;
52 } 56 }
@@ -54,6 +58,7 @@ abstract class DisposableInterface { @@ -54,6 +58,7 @@ abstract class DisposableInterface {
54 // Internal callback that starts the cycle of this controller. 58 // Internal callback that starts the cycle of this controller.
55 void _onStart() { 59 void _onStart() {
56 onInit(); 60 onInit();
  61 + _initialized = true;
57 SchedulerBinding.instance?.addPostFrameCallback((_) => onReady()); 62 SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
58 } 63 }
59 64