Giter Club home page Giter Club logo

flutter_clean_architecture's Introduction

πŸš€ Project using Clean Architecture recommend by Google Developer

This guide encompasses best practices and recommended architecture for building robust, high-quality apps

Medium

πŸš€ Introduction

This sample demonstrates how one can

  • Setup base architecture of Flutter app using Clean Architecture
  • Use dependency injection for layers separation
  • Make api calls using Axios plugin.
β”œβ”€β”€ common
|   └── helper
β”œβ”€β”€ data
|   β”œβ”€β”€ config
|   β”œβ”€β”€ datasources
|   β”œβ”€β”€ gateway
|   β”œβ”€β”€ helper
|   β”œβ”€β”€ models
|   └── repositories
β”œβ”€β”€ di (dependency injection)
β”œβ”€β”€ domain 
|   β”œβ”€β”€ entities
|   β”œβ”€β”€ repositories
|   └── usecases
└── presentation
    β”œβ”€β”€ assests
    β”œβ”€β”€ components
    β”œβ”€β”€ contants
    β”œβ”€β”€ features
    β”œβ”€β”€ localizations
    β”œβ”€β”€ navigations
    └── utils

Dependencies

  • Dio : http client
  • Get_it : dependency injection
  • Build runner : The build_runner package provides a concrete way of generating files using Dart code. Files are always generated directly on disk, and rebuilds are incremental - inspired by tools such as Bazel
  • Rxdart : RxDart extends the capabilities of Dart Streams and StreamControllers.
  • Dartz : Functional programming in Dart.

πŸš€ Module Structure

Clean Architecture

There are 3 main modules to help separate the code. They are Data, Domain, and Presentaion.

  • Data contains Local Storage, APIs, Data objects (Request/Response object, DB objects), and the repository implementation.

  • Domain contains UseCases, Domain Objects/Models, and Repository Interfaces

  • Presentaion contains UI, View Objects, Widgets, etc. Can be split into separate modules itself if needed. For example, we could have a module called Device handling things like camera, location, etc.

πŸš€ Flutter version: channel stable

environment:
  sdk: '>=3.2.0-16.0.dev <4.0.0'
  dart: ">=3.2.0-16.0.dev <4.0.0"
  flutter: ">=3.10.0"
Flutter 3.19.6 β€’ channel stable β€’ https://github.com/flutter/flutter.git
Framework β€’ revision 54e66469a9 (5 days ago) β€’ 2024-04-17 13:08:03 -0700
Engine β€’ revision c4cd48e186
Tools β€’ Dart 3.3.4 β€’ DevTools 2.31.1

πŸš€ Detail overview

  • Using modular architecture to architect the app per feature to be easier and more readable and isolate the feature from each other

Repository

  • Bridge between Data layer and Domain layer
  • Connects to data sources and returns mapped data
  • Data sources include DB and Api

- DataSource:

class PhotoRemoteDataSourceImpl implements PhotoRemoteDataSource {
  final RestApiGateway _restApiGateway;

  PhotoRemoteDataSourceImpl(this._restApiGateway);

  @override
  Future<PhotosResponse> getPhoto(RequestPhoto? reqParams) async {
    final response = await _restApiGateway.dio.get(
        "?key=${API_KEY}&q=${reqParams?.query}&page=${reqParams?.page}&per_page=20");
    if (response.statusCode == 200) {
      return PhotosResponse.fromJson(response.data);
    } else {
      throw const ServerFailure('Lα»—i xαΊ£y ra');
    }
  }
}

- RepositoryImpl:

class PhotoRepositoryImpl implements PhotoRepository {
  final PhotoRemoteDataSource _dataSource;

  PhotoRepositoryImpl(this._dataSource);

  @override
  Future<Either<Failure, Photos>> getPhoto(RequestPhoto? reqParams) async {
    try {
      var response = await _dataSource.getPhoto(reqParams);
      return Right(response.toEntity());
    } on DioException catch (e) {
      return Left(ServerFailure(e.message ?? 'Lα»—i hệ thα»‘ng'));
    }
  }
}

Domain

  • Responsible for connecting to repository to retrieve necessary data. returns a Stream that will emit each update.
  • This is where the business logic takes place.
  • Returns data downstream.
  • Single use.
  • Lives in Domain (No Platform dependencies. Very testable).

- UseCase:

class GetPhotoUseCase implements BaseUseCase<Photos, RequestPhoto> {
  final PhotoRepository repository;

  GetPhotoUseCase(this.repository);

  @override
  Future<Either<Failure, Photos>> execute(RequestPhoto? reqParams) async {
    return await repository.getPhoto(reqParams);
  }
}

Presentation (Holder)

  • Organizes data and holds View state.
  • Talks to use cases.
class PhotoBloc {
  /// Input
  final Sink<String?> search;
  final Function0<void> dispose;
  final Function0<void> onLoadMore;
  final Function0<void> onRefresh;

  /// Output
  final Stream<PhotoState?> results$;

  factory PhotoCubit(final GetPhotoUseCase getPhoto) {
    final currentPage = BehaviorSubject<int>.seeded(1);
    final onLoadMore = BehaviorSubject<void>();
    final onRefresh = BehaviorSubject<void>();
    final textChangesS = BehaviorSubject<String>();
    final List<Hits> appendPhotos = [];

    final loadMore$ = onLoadMore.doOnData((event) {
      var nextPage = currentPage.value + 1;
      currentPage.add(nextPage);
    }).withLatestFrom(textChangesS, (_, s) => textChangesS.value);

    final refresh$ = onRefresh.doOnData((event) {
      currentPage.add(1);
    }).withLatestFrom(textChangesS, (_, s) => textChangesS.value);

    final search$ = textChangesS.doOnData((event) {
      currentPage.add(1);
    });

    final results = Rx.merge([refresh$, search$, loadMore$])
        .debounceTime(const Duration(milliseconds: 350))
        .switchMap((String keyword) {
      if (keyword.isEmpty) {
        return Stream.value(null);
      } else {
        return Stream.fromFuture(getPhoto
            .execute(RequestPhoto(query: keyword, page: currentPage.value)))
            .flatMap((either) =>
            either.fold((error) {
              return Stream<PhotoState?>.value(
                  PhotoError(error.message.toString()));
            }, (data) {
              FocusManager.instance.primaryFocus?.unfocus();
              if (currentPage.value == 1) {
                appendPhotos.clear();
              }
              appendPhotos.addAll(data.hits as List<Hits>);
              return Stream<PhotoState?>.value(PhotoLoaded(
                  data: appendPhotos,
                  currentPage: currentPage.value,
                  hasReachedMax: appendPhotos.length < data?.totalHits));
            }))
            .startWith(const PhotoLoading())
            .onErrorReturnWith(
                (error, _) => const PhotoError("Đã cΓ³ lα»—i xαΊ£y ra"));
      }
    });
    return PhotoBloc._(
      search: textChangesS.sink,
      onLoadMore: () => onLoadMore.add(null),
      onRefresh: () => onRefresh.add(null),
      results$: results,
      dispose: () {
        textChangesS.close();
        currentPage.close();
        onLoadMore.close();
        onRefresh.close();
      },
    );
  }

  PhotoBloc._({
    required this.search,
    required this.onRefresh,
    required this.onLoadMore,
    required this.results$,
    required this.dispose,
  });
}

Presentation (View)

  • View,updates UI

πŸš€ Screenshoots

Default Search Search keyword (ex: flo)

flutter_clean_architecture's People

Contributors

lamnguyen17 avatar

Stargazers

 avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.