Jonatas

Allow lazyPut to recognize the instance type automatically if no type is provided

Showing 36 changed files with 749 additions and 184 deletions
... ... @@ -96,7 +96,7 @@ Get.put<S>(
bool overrideAbstract = false,
// optional: allows you to create the dependency using function instead of the dependency itself.
FcBuilderFunc<S> builder,
InstanceBuilderCallback<S> builder,
)
```
... ... @@ -106,7 +106,7 @@ Get.put<S>(
Get.lazyPut<S>(
// mandatory: a method that will be executed when your class is called for the first time
// Example: Get.lazyPut<Controller>( () => Controller() )
FcBuilderFunc builder,
InstanceBuilderCallback builder,
// optional: same as Get.put(), it is used for when you want multiple different instance of a same class
// must be unique
... ... @@ -128,7 +128,7 @@ Get.putAsync<S>(
// mandatory: an async method that will be executed to instantiate your class
// Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
FcBuilderFuncAsync<S> builder,
AsyncInstanceBuilderCallback<S> builder,
// optional: same as Get.put(), it is used for when you want multiple different instance of a same class
// must be unique
... ...
... ... @@ -99,7 +99,7 @@ Get.put<S>(
bool overrideAbstract = false,
// optional: allows you to create the dependency using function instead of the dependency itself.
FcBuilderFunc<S> builder,
InstanceBuilderCallback<S> builder,
)
```
... ... @@ -109,7 +109,7 @@ Get.put<S>(
Get.lazyPut<S>(
// mandatory: a method that will be executed when your class is called for the first time
// Example: Get.lazyPut<Controller>( () => Controller() )
FcBuilderFunc builder,
InstanceBuilderCallback builder,
// optional: same as Get.put(), it is used for when you want multiple different instance of a same class
// must be unique
... ... @@ -131,7 +131,7 @@ Get.putAsync<S>(
// mandatory: an async method that will be executed to instantiate your class
// Example: Get.putAsync<YourAsyncClass>( () async => await YourAsyncClass() )
FcBuilderFuncAsync<S> builder,
AsyncInstanceBuilderCallback<S> builder,
// optional: same as Get.put(), it is used for when you want multiple different instance of a same class
// must be unique
... ...
... ... @@ -96,7 +96,7 @@ Get.put<S>(
bool permanent = false,
// opcional: permite criar a dependência usando uma função em vez da dependênia em si
FcBuilderFunc<S> builder,
InstanceBuilderCallback<S> builder,
)
```
... ... @@ -106,7 +106,7 @@ Get.put<S>(
Get.lazyPut<S>(
// obrigatório: um método que vai ser executado quando sua classe é chamada pela primeira vez
// Exemplo: "Get.lazyPut<Controller>( () => Controller()
FcBuilderFunc builder,
InstanceBuilderCallback builder,
// opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe
// precisa ser uma string única
... ... @@ -127,7 +127,7 @@ Get.lazyPut<S>(
Get.putAsync<S>(
// Obrigatório: um método assíncrono que vai ser executado para instanciar sua classe
// Exemplo: Get.putAsyn<YourAsyncClass>( () async => await YourAsyncClass() )
FcBuilderFuncAsync<S> builder,
AsyncInstanceBuilderCallback<S> builder,
// opcional: igual ao Get.put(), é usado quando você precisa de múltiplas instâncias de uma mesma classe
// precisa ser uma string única
... ... @@ -144,7 +144,7 @@ Get.putAsync<S>(
Get.create<S>(
// Obrigatório: Uma função que retorna uma classe que será "fabricada" toda vez que Get.find() for chamado
// Exemplo: Get.create<YourClass>(() => YourClass())
FcBuilderFunc<S> builder,
InstanceBuilderCallback<S> builder,
// opcional: igual ao Get.put(), mas é usado quando você precisa de múltiplas instâncias de uma mesma classe.
// Ú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
Prosseguindo com as diferenças entre os métodos:
- 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.
- 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.
- 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.
... ...
import 'package:get/get.dart';
import '../data/home_model.dart';
import '../data/home_repository.dart';
class HomeController extends GetxController {
HomeController({this.homeRepository});
final HomeRepository homeRepository;
Rx<ApiModel> data = Rx<ApiModel>();
@override
void onInit() => fetchDataFromApi();
void fetchDataFromApi() async {
data.value = await homeRepository.getData();
if (data.value == null) {
Get.snackbar("Error", "Can't connect to server");
}
}
}
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'home_model.dart';
abstract class IHomeProvider {
Future<ApiModel> get();
Future<ApiModel> post(Map<String, dynamic> data);
Future<ApiModel> put(Map<String, dynamic> data);
Future<ApiModel> delete(int id);
}
class HomeProvider implements IHomeProvider {
final Dio dio;
HomeProvider({@required this.dio});
Future<ApiModel> get() async {
try {
final response = await dio.get("https://api.covid19api.com/summary");
return ApiModel.fromJson(response.data);
} catch (e) {
print(e.toString());
return null;
}
}
@override
Future<ApiModel> post(Map<String, dynamic> data) {
throw UnimplementedError();
}
@override
Future<ApiModel> put(Map<String, dynamic> data) {
throw UnimplementedError();
}
@override
Future<ApiModel> delete(int id) {
throw UnimplementedError();
}
}
import 'home_model.dart';
import 'home_provider.dart';
class HomeRepository {
HomeRepository({this.homeProvider});
final HomeProvider homeProvider;
Future<ApiModel> getData() async {
return homeProvider.get();
}
}
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_state/home/bindings/home_binding.dart';
import 'package:get_state/home/views/country_view.dart';
import 'home/views/details_view.dart';
import 'home/views/home_view.dart';
import 'package:get_state/routes/app_pages.dart';
import 'shared/logger/logger_utils.dart';
void main() {
runApp(
GetMaterialApp(
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/',
enableLog: true,
// logWriterCallback: localLogWriter,
getPages: [
GetPage(name: '/', page: () => HomePage(), binding: HomeBinding()),
GetPage(name: '/country', page: () => CountryPage()),
GetPage(name: '/details', page: () => DetailsPage()),
],
),
logWriterCallback: Logger.write,
initialRoute: AppPages.INITIAL,
getPages: AppPages.routes,
);
}
// Sample of abstract logging function
void localLogWriter(String text, {bool isError = false}) {
print('** ' + text + ' [' + isError.toString() + ']');
}
}
... ...
import 'package:dio/dio.dart';
import 'package:get/get.dart';
import '../controllers/home_controller.dart';
import '../data/home_provider.dart';
import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
import '../data/home_repository.dart';
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut<HomeController>(() {
Get.put(Dio());
Get.put(HomeProvider(dio: Get.find()));
Get.put(HomeRepository(homeProvider: Get.find()));
return HomeController(homeRepository: Get.find());
});
Get.lazyPut(() => Dio());
Get.lazyPut<IHomeRepository>(() => HomeRepository(dio: Get.find()));
Get.lazyPut(() => HomeController(homeRepository: Get.find()));
}
}
... ...
import 'package:dio/dio.dart';
import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
class HomeRepository implements IHomeRepository {
HomeRepository({this.dio});
final Dio dio;
@override
Future<CasesModel> getCases() async {
try {
final response = await dio.get("https://api.covid19api.com/summary");
return CasesModel.fromJson(response.data);
} catch (e) {
print(e.toString());
return Future.error(e.toString());
}
}
}
... ...
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
abstract class IHomeRepository {
Future<CasesModel> getCases();
}
... ...
// To parse this JSON data, do
//
// final apiModel = apiModelFromJson(jsonString);
// final CasesModel = CasesModelFromJson(jsonString);
import 'dart:convert';
class ApiModel {
class CasesModel {
final Global global;
final List<Country> countries;
final String date;
ApiModel({
CasesModel({
this.global,
this.countries,
this.date,
});
factory ApiModel.fromRawJson(String str) =>
ApiModel.fromJson(json.decode(str));
factory CasesModel.fromRawJson(String str) =>
CasesModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory ApiModel.fromJson(Map<String, dynamic> json) => ApiModel(
factory CasesModel.fromJson(Map<String, dynamic> json) => CasesModel(
global: json["Global"] == null ? null : Global.fromJson(json["Global"]),
countries: json["Countries"] == null
? null
... ...
import 'package:get/get.dart';
import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
enum Status { loading, success, error }
class HomeController extends GetxController {
HomeController({this.homeRepository});
/// inject repo abstraction dependency
final IHomeRepository homeRepository;
/// create a reactive status from request with initial value = loading
final status = Status.loading.obs;
/// create a reactive CasesModel. CasesModel().obs has same result
final cases = Rx<CasesModel>();
/// When the controller is initialized, make the http request
@override
void onInit() => fetchDataFromApi();
/// fetch cases from Api
Future<void> fetchDataFromApi() async {
/// When the repository returns the value, change the status to success, and fill in "cases"
return homeRepository.getCases().then(
(data) {
cases(data);
status(Status.success);
},
/// In case of error, print the error and change the status to Status.error
onError: (err) {
print("$err");
return status(Status.error);
},
);
}
}
... ...
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get_state/home/controllers/home_controller.dart';
import 'package:get_state/home/data/home_model.dart';
import 'package:get/get.dart';
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
import '../controllers/home_controller.dart';
class CountryPage extends GetWidget<HomeController> {
class CountryView extends GetWidget<HomeController> {
@override
Widget build(BuildContext context) {
return Container(
... ... @@ -28,9 +28,9 @@ class CountryPage extends GetWidget<HomeController> {
),
body: Center(
child: ListView.builder(
itemCount: controller.data.value.countries.length,
itemCount: controller.cases.value.countries.length,
itemBuilder: (context, index) {
Country country = controller.data.value.countries[index];
Country country = controller.cases.value.countries[index];
return ListTile(
onTap: () {
Get.toNamed('/details', arguments: country);
... ...
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_state/home/data/home_model.dart';
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
class DetailsPage extends StatelessWidget {
class DetailsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
Country country = Get.arguments;
... ...
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_state/home/controllers/home_controller.dart';
import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
class HomePage extends GetWidget<HomeController> {
class HomeView extends GetView<HomeController> {
@override
Widget build(BuildContext context) {
return Container(
... ... @@ -23,9 +23,12 @@ class HomePage extends GetWidget<HomeController> {
centerTitle: true,
),
body: Center(
child: Obx(() => (controller.data() == null)
? CircularProgressIndicator()
: Column(
child: Obx(
() {
Status status = controller.status.value;
if (status == Status.loading) return CircularProgressIndicator();
if (status == Status.error) return Text('Error on connection :(');
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
... ... @@ -38,9 +41,8 @@ class HomePage extends GetWidget<HomeController> {
),
),
Text(
'${controller.data.value.global.totalConfirmed}',
style:
TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
'${controller.cases.value.global.totalConfirmed}',
style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
... ... @@ -52,9 +54,8 @@ class HomePage extends GetWidget<HomeController> {
),
),
Text(
'${controller.data.value.global.totalDeaths}',
style:
TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
'${controller.cases.value.global.totalDeaths}',
style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold),
),
SizedBox(
height: 10,
... ... @@ -74,7 +75,9 @@ class HomePage extends GetWidget<HomeController> {
),
)
],
)),
);
},
),
),
),
);
... ...
import 'package:get/get.dart';
import 'package:get_state/pages/home/bindings/home_binding.dart';
import 'package:get_state/pages/home/presentation/views/country_view.dart';
import 'package:get_state/pages/home/presentation/views/details_view.dart';
import 'package:get_state/pages/home/presentation/views/home_view.dart';
part 'app_routes.dart';
class AppPages {
static const INITIAL = Routes.HOME;
static final routes = [
GetPage(
name: Routes.HOME,
page: () => HomeView(),
binding: HomeBinding(),
),
GetPage(
name: Routes.COUNTRY,
page: () => CountryView(),
),
GetPage(
name: Routes.DETAILS,
page: () => DetailsView(),
),
];
}
... ...
part of 'app_pages.dart';
abstract class Routes{
static const HOME = '/home';
static const COUNTRY = '/country';
static const DETAILS = '/details';
}
\ No newline at end of file
... ...
class Logger {
// Sample of abstract logging function
static void write(String text, {bool isError = false}) {
print('** ' + text + ' [' + isError.toString() + ']');
}
}
... ...
flutter/ephemeral
... ...
cmake_minimum_required(VERSION 3.10)
project(runner LANGUAGES CXX)
set(BINARY_NAME "example")
set(APPLICATION_ID "com.example.example")
cmake_policy(SET CMP0063 NEW)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
# Configure build options.
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
endif()
# Compilation settings that should be applied to most targets.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
# Flutter library and tool build rules.
add_subdirectory(${FLUTTER_MANAGED_DIR})
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
# Application build
add_executable(${BINARY_NAME}
"main.cc"
"my_application.cc"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
)
apply_standard_settings(${BINARY_NAME})
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
add_dependencies(${BINARY_NAME} flutter_assemble)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# By default, "installing" just makes a relocatable bundle in the build
# directory.
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
# Start with a clean build bundle directory every time.
install(CODE "
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
" COMPONENT Runtime)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
endif()
... ...
cmake_minimum_required(VERSION 3.10)
set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral")
# Configuration provided via flutter tool.
include(${EPHEMERAL_DIR}/generated_config.cmake)
# TODO: Move the rest of this into files in ephemeral. See
# https://github.com/flutter/flutter/issues/57146.
# Serves the same purpose as list(TRANSFORM ... PREPEND ...),
# which isn't available in 3.10.
function(list_prepend LIST_NAME PREFIX)
set(NEW_LIST "")
foreach(element ${${LIST_NAME}})
list(APPEND NEW_LIST "${PREFIX}${element}")
endforeach(element)
set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE)
endfunction()
# === Flutter Library ===
# System-level dependencies.
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0)
pkg_check_modules(BLKID REQUIRED IMPORTED_TARGET blkid)
set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so")
# Published to parent scope for install step.
set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE)
set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE)
set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE)
set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE)
list(APPEND FLUTTER_LIBRARY_HEADERS
"fl_basic_message_channel.h"
"fl_binary_codec.h"
"fl_binary_messenger.h"
"fl_dart_project.h"
"fl_engine.h"
"fl_json_message_codec.h"
"fl_json_method_codec.h"
"fl_message_codec.h"
"fl_method_call.h"
"fl_method_channel.h"
"fl_method_codec.h"
"fl_method_response.h"
"fl_plugin_registrar.h"
"fl_plugin_registry.h"
"fl_standard_message_codec.h"
"fl_standard_method_codec.h"
"fl_string_codec.h"
"fl_value.h"
"fl_view.h"
"flutter_linux.h"
)
list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/")
add_library(flutter INTERFACE)
target_include_directories(flutter INTERFACE
"${EPHEMERAL_DIR}"
)
target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}")
target_link_libraries(flutter INTERFACE
PkgConfig::GTK
PkgConfig::GLIB
PkgConfig::GIO
PkgConfig::BLKID
)
add_dependencies(flutter flutter_assemble)
# === Flutter tool backend ===
# _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the
# flutter tool.
add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CMAKE_CURRENT_BINARY_DIR}/_phony_
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
linux-x64 ${CMAKE_BUILD_TYPE}
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
${FLUTTER_LIBRARY_HEADERS}
)
... ...
//
// Generated file. Do not edit.
//
#include "generated_plugin_registrant.h"
void fl_register_plugins(FlPluginRegistry* registry) {
}
... ...
//
// Generated file. Do not edit.
//
#ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_
#include <flutter_linux/flutter_linux.h>
// Registers Flutter plugins.
void fl_register_plugins(FlPluginRegistry* registry);
#endif // GENERATED_PLUGIN_REGISTRANT_
... ...
#
# Generated file, do not edit.
#
list(APPEND FLUTTER_PLUGIN_LIST
)
set(PLUGIN_BUNDLED_LIBRARIES)
foreach(plugin ${FLUTTER_PLUGIN_LIST})
add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin})
target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${plugin}_plugin>)
list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
endforeach(plugin)
... ...
#include "my_application.h"
int main(int argc, char** argv) {
// Only X11 is currently supported.
// Wayland support is being developed: https://github.com/flutter/flutter/issues/57932.
gdk_set_allowed_backends("x11");
g_autoptr(MyApplication) app = my_application_new();
return g_application_run(G_APPLICATION(app), argc, argv);
}
... ...
#include "my_application.h"
#include <flutter_linux/flutter_linux.h>
#include "flutter/generated_plugin_registrant.h"
struct _MyApplication {
GtkApplication parent_instance;
};
G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)
// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
GtkWindow* window =
GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application)));
GtkHeaderBar *header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
gtk_widget_show(GTK_WIDGET(header_bar));
gtk_header_bar_set_title(header_bar, "example");
gtk_header_bar_set_show_close_button(header_bar, TRUE);
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
gtk_window_set_default_size(window, 1280, 720);
gtk_widget_show(GTK_WIDGET(window));
g_autoptr(FlDartProject) project = fl_dart_project_new();
FlView* view = fl_view_new(project);
gtk_widget_show(GTK_WIDGET(view));
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
gtk_widget_grab_focus(GTK_WIDGET(view));
}
static void my_application_class_init(MyApplicationClass* klass) {
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
}
static void my_application_init(MyApplication* self) {}
MyApplication* my_application_new() {
return MY_APPLICATION(g_object_new(my_application_get_type(),
"application-id", APPLICATION_ID,
nullptr));
}
... ...
#ifndef FLUTTER_MY_APPLICATION_H_
#define FLUTTER_MY_APPLICATION_H_
#include <gtk/gtk.h>
G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION,
GtkApplication)
/**
* my_application_new:
*
* Creates a new Flutter-based application.
*
* Returns: a new #MyApplication.
*/
MyApplication* my_application_new();
#endif // FLUTTER_MY_APPLICATION_H_
... ...
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
version: "7.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
version: "0.39.17"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.0"
async:
dependency: transitive
description:
... ... @@ -15,6 +36,27 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0-nullsafety"
build:
dependency: transitive
description:
name: build
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
built_collection:
dependency: transitive
description:
name: built_collection
url: "https://pub.dartlang.org"
source: hosted
version: "4.3.2"
built_value:
dependency: transitive
description:
name: built_value
url: "https://pub.dartlang.org"
source: hosted
version: "7.1.0"
characters:
dependency: transitive
description:
... ... @@ -29,6 +71,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0-nullsafety"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
clock:
dependency: transitive
description:
... ... @@ -36,6 +85,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety"
code_builder:
dependency: transitive
description:
name: code_builder
url: "https://pub.dartlang.org"
source: hosted
version: "3.4.1"
collection:
dependency: transitive
description:
... ... @@ -43,6 +99,34 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0-nullsafety.2"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.5"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.dartlang.org"
source: hosted
version: "0.16.2"
dart_style:
dependency: transitive
description:
name: dart_style
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.6"
dio:
dependency: "direct main"
description:
... ... @@ -57,6 +141,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0-nullsafety"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.11"
flutter:
dependency: "direct main"
description: flutter
... ... @@ -74,6 +165,20 @@ packages:
relative: true
source: path
version: "3.5.1"
glob:
dependency: transitive
description:
name: glob
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
html:
dependency: transitive
description:
name: html
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.0+3"
http_parser:
dependency: transitive
description:
... ... @@ -81,6 +186,20 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.4"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.2"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.4"
matcher:
dependency: transitive
description:
... ... @@ -95,6 +214,34 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0-nullsafety.2"
mockito:
dependency: "direct main"
description:
name: mockito
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.2"
node_interop:
dependency: transitive
description:
name: node_interop
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
package_config:
dependency: transitive
description:
name: package_config
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.3"
path:
dependency: transitive
description:
... ... @@ -102,11 +249,39 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0-nullsafety"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.9.2"
pub_semver:
dependency: transitive
description:
name: pub_semver
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.4"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.6"
source_span:
dependency: transitive
description:
... ... @@ -163,5 +338,19 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0-nullsafety.2"
watcher:
dependency: transitive
description:
name: watcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.7+15"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.1"
sdks:
dart: ">=2.10.0-0.0.dev <2.10.0"
... ...
... ... @@ -29,6 +29,7 @@ dependencies:
get:
path: ../
dio: ^3.0.9
mockito: 4.1.2
dev_dependencies:
flutter_test:
... ...
import 'dart:math';
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';
import 'package:get_state/pages/home/domain/adapters/repository_adapter.dart';
import 'package:get_state/pages/home/domain/entity/cases_model.dart';
import 'package:get_state/pages/home/presentation/controllers/home_controller.dart';
import 'package:matcher/matcher.dart';
class MockReposity implements IHomeRepository {
@override
Future<CasesModel> getCases() async {
await Future.delayed(Duration(milliseconds: 100));
return Random().nextBool()
? CasesModel(
global: Global(totalDeaths: 100, totalConfirmed: 200),
)
: Future.error('error');
}
}
void main() {
final binding = BindingsBuilder(() {
Get.lazyPut<IHomeRepository>(() => MockReposity());
Get.lazyPut<HomeController>(
() => HomeController(homeRepository: Get.find()));
});
test('Test Binding', () {
expect(Get.isPrepared<HomeController>(), false);
expect(Get.isPrepared<IHomeRepository>(), false);
/// test you Binding class with BindingsBuilder
binding.builder();
expect(Get.isPrepared<HomeController>(), true);
expect(Get.isPrepared<IHomeRepository>(), true);
Get.reset();
});
test('Test Controller', () async {
/// Controller can't be on memory
expect(() => Get.find<HomeController>(), throwsA(TypeMatcher<String>()));
/// build Binding
binding.builder();
/// recover your controller
HomeController controller = Get.find();
/// check if onInit was called
expect(controller.initialized, true);
/// check initial Status
expect(controller.status.value, Status.loading);
/// await time request
await Future.delayed(Duration(milliseconds: 100));
if (controller.status.value == Status.error) {
expect(controller.cases.value, null);
}
if (controller.status.value == Status.success) {
expect(controller.cases.value.global.totalDeaths, 100);
expect(controller.cases.value.global.totalConfirmed, 200);
}
});
}
... ...
// // This is a basic Flutter widget test.
// //
// // To perform an interaction with a widget in your test, use the WidgetTester
// // utility that Flutter provides. For example, you can send tap and scroll
// // gestures. You can also use WidgetTester to find child widgets in the widget
// // tree, read text, and verify that the values of widget properties are correct.
// import 'package:flutter/material.dart';
// import 'package:flutter_test/flutter_test.dart';
// import 'package:get_state/main.dart';
// void main() {
// testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// // Build our app and trigger a frame.
// await tester.pumpWidget(MyApp());
// // Verify that our counter starts at 0.
// expect(find.text('0'), findsOneWidget);
// expect(find.text('1'), findsNothing);
// // Tap the '+' icon and trigger a frame.
// await tester.tap(find.byIcon(Icons.add));
// await tester.pump();
// // Verify that our counter has incremented.
// expect(find.text('0'), findsNothing);
// expect(find.text('1'), findsOneWidget);
// });
// }
... ... @@ -3,11 +3,12 @@ import 'package:get/src/core/get_interface.dart';
import 'get_instance.dart';
extension Inst on GetInterface {
void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
void lazyPut<S>(InstanceBuilderCallback<S> builder,
{String tag, bool fenix = false}) {
return GetInstance().lazyPut<S>(builder, tag: tag, fenix: fenix);
}
Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
{String tag, bool permanent = false}) async =>
GetInstance().putAsync<S>(builder, tag: tag, permanent: permanent);
... ... @@ -22,7 +23,7 @@ extension Inst on GetInterface {
/// Repl b = find();
/// print(a==b); (false)```
///
void create<S>(FcBuilderFunc<S> builder,
void create<S>(InstanceBuilderCallback<S> builder,
{String name, bool permanent = true}) =>
GetInstance().create<S>(builder, name: name, permanent: permanent);
... ... @@ -42,7 +43,9 @@ extension Inst on GetInterface {
/// rules
///
S put<S>(S dependency,
{String tag, bool permanent = false, FcBuilderFunc<S> builder}) =>
{String tag,
bool permanent = false,
InstanceBuilderCallback<S> builder}) =>
GetInstance()
.put<S>(dependency, tag: tag, permanent: permanent, builder: builder);
... ... @@ -55,4 +58,6 @@ extension Inst on GetInterface {
GetInstance().delete<S>(tag: tag, key: key);
bool isRegistered<S>({String tag}) => GetInstance().isRegistered<S>(tag: tag);
bool isPrepared<S>({String tag}) => GetInstance().isPrepared<S>(tag: tag);
}
... ...
... ... @@ -27,12 +27,13 @@ class GetInstance {
static GetQueue _queue = GetQueue();
void lazyPut<S>(FcBuilderFunc builder, {String tag, bool fenix = false}) {
void lazyPut<S>(InstanceBuilderCallback<S> builder,
{String tag, bool fenix = false}) {
String key = _getKey(S, tag);
_factory.putIfAbsent(key, () => _Lazy(builder, fenix));
}
Future<S> putAsync<S>(FcBuilderFuncAsync<S> builder,
Future<S> putAsync<S>(AsyncInstanceBuilderCallback<S> builder,
{String tag, bool permanent = false}) async {
return put<S>(await builder(), tag: tag, permanent: permanent);
}
... ... @@ -49,7 +50,7 @@ class GetInstance {
S dependency, {
String tag,
bool permanent = false,
FcBuilderFunc<S> builder,
InstanceBuilderCallback<S> builder,
}) {
_insert(
isSingleton: true,
... ... @@ -70,7 +71,7 @@ class GetInstance {
/// Repl b = find();
/// print(a==b); (false)```
void create<S>(
FcBuilderFunc<S> builder, {
InstanceBuilderCallback<S> builder, {
String name,
bool permanent = true,
}) {
... ... @@ -83,7 +84,7 @@ class GetInstance {
bool isSingleton,
String name,
bool permanent = false,
FcBuilderFunc<S> builder,
InstanceBuilderCallback<S> builder,
}) {
assert(builder != null);
final key = _getKey(S, name);
... ... @@ -180,7 +181,7 @@ class GetInstance {
S find<S>({String tag}) {
String key = _getKey(S, tag);
if (isRegistered<S>(tag: tag)) {
_FcBuilder builder = _singl[key] as _FcBuilder;
_FcBuilder builder = _singl[key];
if (builder == null) {
if (tag == null) {
throw 'Class "$S" is not register';
... ... @@ -245,7 +246,7 @@ class GetInstance {
return false;
}
_FcBuilder builder = _singl[newKey] as _FcBuilder;
_FcBuilder builder = _singl[newKey];
if (builder.permanent && !force) {
GetConfig.log(
'"$newKey" has been marked as permanent, SmartManagement is not authorized to delete it.',
... ... @@ -280,9 +281,9 @@ class GetInstance {
bool isPrepared<S>({String tag}) => _factory.containsKey(_getKey(S, tag));
}
typedef FcBuilderFunc<S> = S Function();
typedef InstanceBuilderCallback<S> = S Function();
typedef FcBuilderFuncAsync<S> = Future<S> Function();
typedef AsyncInstanceBuilderCallback<S> = Future<S> Function();
/// Internal class to register instances with Get.[put]<[S]>().
class _FcBuilder<S> {
... ... @@ -295,7 +296,7 @@ class _FcBuilder<S> {
/// Generates (and regenerates) the instance when [isSingleton]=false.
/// Usually used by factory methods
FcBuilderFunc<S> builderFunc;
InstanceBuilderCallback<S> builderFunc;
/// Flag to persist the instance in memory,
/// without considering [GetConfig.smartManagement]
... ... @@ -315,6 +316,6 @@ class _FcBuilder<S> {
/// keeps a reference to the callback to be called.
class _Lazy {
bool fenix;
FcBuilderFunc builder;
InstanceBuilderCallback builder;
_Lazy(this.builder, this.fenix);
}
... ...
... ... @@ -730,7 +730,7 @@ extension GetNavigation on GetInterface {
Text(
title,
style: TextStyle(
color: colorText ?? theme.iconTheme.color,
color: colorText ?? Colors.black,
fontWeight: FontWeight.w800,
fontSize: 16),
),
... ... @@ -738,7 +738,7 @@ extension GetNavigation on GetInterface {
Text(
message,
style: TextStyle(
color: colorText ?? theme.iconTheme.color,
color: colorText ?? Colors.black,
fontWeight: FontWeight.w300,
fontSize: 14),
),
... ...
... ... @@ -19,7 +19,7 @@ abstract class Bindings {
/// ````
class BindingsBuilder extends Bindings {
/// Register your dependencies in the [builder] callback.
final Function() builder;
final void Function() builder;
BindingsBuilder(this.builder);
... ...
... ... @@ -42,9 +42,13 @@ abstract class DisposableInterface {
/// It uses an internal "callable" type, to avoid any @overrides in subclases.
/// This method should be internal and is required to define the lifetime cycle
/// of the subclass.
///
final onStart = _InternalFinalCallback<void>();
bool _initialized = false;
/// Checks whether the controller has already been initialized.
bool get initialized => _initialized;
DisposableInterface() {
onStart.callback = _onStart;
}
... ... @@ -52,6 +56,7 @@ abstract class DisposableInterface {
// Internal callback that starts the cycle of this controller.
void _onStart() {
onInit();
_initialized = true;
SchedulerBinding.instance?.addPostFrameCallback((_) => onReady());
}
... ...