flutter-dasher

所属分类:Flutter开发
开发工具:Dart
文件大小:0KB
下载次数:0
上传日期:2024-01-18 09:50:27
上 传 者sh-1993
说明:  颤振阻尼器
(flutter dasher)

文件列表:
.fvm/
.run/
__brick__/
android/
assets/
hooks/
ios/
lib/
test/
.metadata
CHANGELOG.md
LICENSE
TUTORIAL.md
analysis_options.yaml
brick.yaml
pubspec.lock
pubspec.yaml

# Table of contents - [Flutter Clean Architecture Sample App - Dasher](https://github.com/infinum/flutter-dasher/blob/master/#flutter-clean-architecture-sample-app---dasher) - [Architecture structure](https://github.com/infinum/flutter-dasher/blob/master/#architecture-structure) * [Presentation](https://github.com/infinum/flutter-dasher/blob/master/#presentation) + [Widgets (UI)](https://github.com/infinum/flutter-dasher/blob/master/#widgets--ui-) + [Presenter](https://github.com/infinum/flutter-dasher/blob/master/#presenter) * [Domain](https://github.com/infinum/flutter-dasher/blob/master/#domain) + [Interactor](https://github.com/infinum/flutter-dasher/blob/master/#interactor) + [Data Holder](https://github.com/infinum/flutter-dasher/blob/master/#data-holder) * [Outer layer](https://github.com/infinum/flutter-dasher/blob/master/#outer-layer) + [Repository](https://github.com/infinum/flutter-dasher/blob/master/#repository) + [Source remote](https://github.com/infinum/flutter-dasher/blob/master/#source-remote) + [Source local](https://github.com/infinum/flutter-dasher/blob/master/#source-local) + [Device](https://github.com/infinum/flutter-dasher/blob/master/#device) - [Folder structure](https://github.com/infinum/flutter-dasher/blob/master/#folder-structure) - [Riverpod and GetIt](https://github.com/infinum/flutter-dasher/blob/master/#riverpod-and-getit) - [Example of architecture flow](https://github.com/infinum/flutter-dasher/blob/master/#example-of-architecture-flow) * [Presentation](https://github.com/infinum/flutter-dasher/blob/master/#presentation-1) + [Widget](https://github.com/infinum/flutter-dasher/blob/master/#widget) + [Presenter](https://github.com/infinum/flutter-dasher/blob/master/#presenter-1) * [Domain](https://github.com/infinum/flutter-dasher/blob/master/#domain-1) + [Interactor](https://github.com/infinum/flutter-dasher/blob/master/#interactor-1) + [Repository](https://github.com/infinum/flutter-dasher/blob/master/#repository-1) - [Screenshots](https://github.com/infinum/flutter-dasher/blob/master/#screenshots) - [Infinum architecture Mason brick](https://github.com/infinum/flutter-dasher/blob/master/#infinum-architecture-mason-brick) * [How to use](https://github.com/infinum/flutter-dasher/blob/master/#how-to-use) + [Tools to install](https://github.com/infinum/flutter-dasher/blob/master/#tools-to-install) + [Create new project](https://github.com/infinum/flutter-dasher/blob/master/#create-new-project) + [Mason brick setup](https://github.com/infinum/flutter-dasher/blob/master/#mason-brick-setup) * [Variables](https://github.com/infinum/flutter-dasher/blob/master/#variables) * [Outputs](https://github.com/infinum/flutter-dasher/blob/master/#outputs) # Flutter Clean Architecture Sample App - Dasher This project is a starting point for a Flutter application. Dasher App will introduce you to clean architecture structure and how inner / outer layers are connected. # Architecture structure Dasher app uses the architecture structure described in [handbook](https://github.com/infinum/flutter-dasher/blob/master/https://infinum.com/handbook/flutter/architecture/architecture). ![flutter-architecture-layers](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178720727-76ff7094-3f48-4127-b7ca-376f91e69682.png) ## Presentation There is no business logic on this layer, it is only used to show UI and handle events. Read more about Presentation layer in [handbook](https://github.com/infinum/flutter-dasher/blob/master/https://infinum.com/handbook/flutter/architecture/architecture#presenters-and-widgets). ### Widgets (UI) - Notify presenter of events such as screen display and user touch events. - Observes presenter state and can rebuild on state change. ### Presenter - Contains presentation logic, usually controlling the view state. ## Domain This layer is responsible for business logic. ### Interactor - The main job of the interactor is combining different repositories and handling business logic. ### Data Holder - Singleton class that holds data in memory, that doesn't call repositories or other outer layers. ## Outer layer ### Repository - It uses concrete implementations like dio, hive, add2calendar, other plugins and abstracts them from the rest of the application. - Repository should be behind and interface. - Interface belongs to the domain and the implementation belongs to the outer layers. ### Source remote - Represents communication with remote sources (web, http clients, sockets). ### Source local - Represents communication with local sources (database, shared_prefs). ### Device - Represents communication with device hardware (e.g. sensors) or software (calendar, permissions). # Folder structure Top-level folder structure you will find in the project under the /lib: img_project_structure - **app** contains app run_app with various setups like the setup of flutter.onError crash handling and dependency initialization. - **common** contains code that's common to all layers and accessible by all layers. - **device** is an outer layer that represents communication with device hardware (e.g. sensors) or software (calendar, permissions). - **domain** is the inner layer that usually contains interactors, data holders. This layer should only contain business logic and not know about specific of ui, web, etc. or other layers. - **source_local** is an outer layer that represents communication with local sources (database, shared_prefs). - **source_remote** is an outer layer that represents communication with remote sources (web, http clients, sockets). - **ui** is the layer where we package by feature widgets and presenters. Presenters contains presentation logic and they access domain and are provided in the view tree by Provider/Riverpod package. - **main_production.dart** and **main_staging.dart** two versions of main file, each version has it's own flavor in practice this usually means having two versions. Find more about flavors [here](https://github.com/infinum/flutter-dasher/blob/master/https://infinum.com/handbook/flutter/project-flow/flutter-flavors). # Riverpod and GetIt This architecture structure is using [Riverpod](https://github.com/infinum/flutter-dasher/blob/master/https://riverpod.dev/) for Presentation layer and [GetIt](https://github.com/infinum/flutter-dasher/blob/master/https://pub.dev/packages/get_it) for Domain and outer layers (source remote, source local and device). Read more about how to use riverpod in [handbook](https://github.com/infinum/flutter-dasher/blob/master/https://infinum.com/handbook/flutter/architecture/using-riverpod). ![flutter-architecture-layers-riverpod-getit](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178723072-9a2823cc-6b4d-4d15-be04-a6f5fd0bba97.png) # Example of architecture flow In this example, we'll show the architecture flow for fetching new Tweets on the Dashboard screen. ## Presentation ### Widget ![flutter-architecture-layers-riverpod-getit (2)](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178748869-3200cf10-0505-4aba-ad7b-f90e4e471ffb.png) One of the widgets on the Dashboard screen is `DasherTweetsList`. Inside the Tweets list widget is created reference to watch `feedRequestPresenter`. ```dart final _presenter = ref.watch(feedRequestPresenter); ``` ### Presenter ![flutter-architecture-layers-riverpod-getit (3)](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178749119-d3928b11-0a4e-4899-890c-da310c467b5d.png) For `FeedRequestPresenter` we are using `RequestProvider`, you can find more about it [here](https://github.com/infinum/flutter-dasher/blob/master/https://github.com/infinum/flutter-bits/tree/master/request_provider). Inside `FeedRequestPresenter` we created instance of `FetchFeedInteractor` interface. ```dart final feedRequestPresenter = ChangeNotifierProvider.autoDispose( (ref) => FeedRequestPresenter(GetIt.instance.get()), ); class FeedRequestPresenter extends RequestProvider> { FeedRequestPresenter(this._feedTimelineInteractor) { fetchTweetsTimeline(); } final FetchFeedInteractor _feedTimelineInteractor; Future fetchTweetsTimeline() { return executeRequest(requestBuilder: _feedTimelineInteractor.fetchFeedTimeline); } } ``` From this part, we slowly transition toward Domain layer. ## Domain ### Interactor ![flutter-architecture-layers-riverpod-getit (4)](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178749319-34a00de7-1f33-438d-b501-ecd80ad1b88f.png) Domain is a business logic layer, where we have an implementation of `FetchFeedInteractor` called `FetchFeedInteractorImpl`. Our task is to create an instance of Repository which is responsible for handling outer logic for getting user timeline tweets. `FeedRepository` is also behind an interface. ```dart class FetchFeedInteractorImpl implements FetchFeedInteractor { FetchFeedInteractorImpl(this._feedRepository); final FeedRepository _feedRepository; @override Future> fetchFeedTimeline() { return _feedRepository.fetchFeedTimeline(); } } ``` ### Repository ![flutter-architecture-layers-riverpod-getit (5)](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178749678-9b33376c-5144-4644-855b-786cac657827.png) `FeedRepositoryImpl` is part of Source remote layer. This repository is using [twitter_api_v2](https://github.com/infinum/flutter-dasher/blob/master/https://pub.dev/packages/twitter_api_v2) package for fetching data from Twitter's API. ```dart Future> fetchFeedTimeline() async { final response = await twitterApi.tweetsService.lookupHomeTimeline( userId: userDataHolder.user!.id, tweetFields: [ TweetField.publicMetrics, TweetField.createdAt, ], userFields: [ UserField.createdAt, UserField.profileImageUrl, ], expansions: [ TweetExpansion.authorId, ], ); return _getTweetsListWithAuthors(response); } ``` after a successful response, data is passed back to `FeedRequestPresenter` in his state, and it triggers state listeners. Inside the build method of `DasherTweetsList` we use state listeners of `FeedRequestPresenter` so we can easily show/hide widgets depending on the emitted event. ![flutter-architecture-layers-riverpod-getit (6)](https://github.com/infinum/flutter-dasher/blob/master/https://user-images.githubusercontent.com/1117315/178750109-7e92255e-6894-4b03-aff8-0d6793388afc.png) ```dart _presenter.state.maybeWhen( success: (feed) => _TweetsList( feed: feed, ), initial: () => const CircularProgressIndicator(), loading: (feed) { if (feed == null) { return const CircularProgressIndicator(); } else { return _TweetsList( feed: feed, ); } }, failure: (e) => Text('Error occurred $e'), orElse: () => const CircularProgressIndicator(), ), ``` # Screenshots | Login | Feed | | ----- | ---- | | | | | Profile | New Tweet | | ------- | --------- | | | | # Infinum architecture Mason brick Easiest way to set up our architecture in the project is with usage of [Mason](https://github.com/infinum/flutter-dasher/blob/master/https://pub.dev/packages/mason_cli) bricks. The infinum_architecture brick is published on https://brickhub.dev/bricks/infinum_architecture/ and it will generate all the required directories and files ready to start the project. ## How to use ### Tools to install Make sure you have installed [FVM - Flutter Version Management](https://github.com/infinum/flutter-dasher/blob/master/https://fvm.app/docs/getting_started/installation). ``` dart pub global activate fvm ``` Also install [Mason CLI](https://github.com/infinum/flutter-dasher/blob/master/https://pub.dev/packages/mason_cli) it's must have for using Mason bricks. ``` dart pub global activate mason_cli ``` ### Create new project Create new Flutter project: ``` flutter create {project_name} ``` move to project folder: ``` cd {project_name} ``` ### Mason brick setup Initialize mason: ``` mason init ``` Add mason brick to your project: ``` mason add infinum_architecture ``` Start generating Infinum architecture folder structure: ``` mason make infinum_architecture --on-conflict overwrite ``` ## Variables | Variable | Description | Default | Type | | ----------------------- | --------------------------------------------------------------------------- | ------- | --------- | | `project_name` | This name is used to name main function and files `run{project_name}App()` | example | `string` | | `flutter_version` | Defines which version of FVM you want to install | stable | `string` | | `brick_look` | Optional Look | true | `bool` | | `brick_request_provider`| Optional Request Provider | true | `bool` | ## Outputs ``` lib ┣ app ┃ ┣ di ┃ ┃ ┗ inject_dependencies.dart ┃ ┣ example_app.dart ┃ ┗ run_example_app.dart ┣ common ┃ ┣ error_handling ┃ ┃ ┣ base ┃ ┃ ┃ ┣ expected_exception.dart ┃ ┃ ┃ ┗ localized_exception.dart ┃ ┃ ┗ error_formatter.dart ┃ ┣ flavor ┃ ┃ ┣ app_build_mode.dart ┃ ┃ ┣ flavor.dart ┃ ┃ ┣ flavor_config.dart ┃ ┃ ┗ flavor_values.dart ┃ ┗ logger ┃ ┣ custom_loggers.dart ┃ ┗ firebase_log_printer.dart ┣ device ┃ ┗ di ┃ ┗ inject_dependencies.dart ┣ domain ┃ ┗ di ┃ ┗ inject_dependencies.dart ┣ source_local ┃ ┗ di ┃ ┗ inject_dependencies.dart ┣ source_remote ┃ ┗ di ┃ ┗ inject_dependencies.dart ┣ ui ┃ ┣ common ┃ ┃ ┣ generic ┃ ┃ ┃ ┗ generic_error.dart ┃ ┗ home ┃ ┗ home_screen.dart ┣ main_production.dart ┗ main_staging.dart ```


近期下载者

相关文件


收藏者