[Flutter development] Personal Flutter Project structure with Repository pattern — Demo app

Before we start

get: ^4.3.8 # place this with latest version if possible
  • classes: We have subfolder bases and utils here. Bases is for defining all Base Class of this project. Utils is for utilities classes.
  • config: The app config. I use it to save app internal data like theme, username,…
  • controller: Controller that connect UI with Repository and define app logic here.
  • model: Data classes use in app and integrating with API.
  • network: Define the way app interact with API.
  • repository: Getting data from internal storage or Internet.
  • ui: UI, screen layout
  • main: Define root of the app
  • pages: Use to define each separate screen (like routes in material app)

Classes

bases folder
  • base_common_widget.dart: This contains some common widget using in entire app. Like show/hide loading, toast message, …
  • base_controller: For each controller in the application should extend this widget (For using or defining common logic or function…)
  • base_screen: Each screen in this application should extend this widget
  • base_view: Each view in this application should extend this widget.
T get controller => GetInstance().find<T>(tag: null);
Get.lazyPut(() => HomeController());
@overrideWidget build(BuildContext context) {return screen(context);}Widget screen(BuildContext context);
utils folder

Config

Models

models folder

Network

network folder
  • services: Contain service for each screen or each module (It based on how you manage your project)
APIProvider _apiProvider = GetInstance().find<APIProvider>();
httpClient.addRequestModifier((request) {return request;});
httpClient.addRequestModifier((request) {      
String token = AppConfig.TOKEN; request.headers['Authorization'] = "Bearer $token";
return request;
});

Repository

Controller

  • _repository: This is for calling api
  • _screenState: An object with RXDart this is where we integrated with GetX state management. When this value change, it will notify to GetX builder to rebuild the widget. So in later, we will see how UI implement GetX builder.
  • screenState: State of screen. It is an int value I define in constants file. (Explain: I use a private variable _screenState for using inside the controller, so the value can be only modified inside the controller itself. From UI, we need a variable to get value, not modify. So the screenState is for it.)
  • listSubCategory: For storing data.
  • fetchHomeData: Call api with repository. We set screen state to loading and then success status, so the UI can know and show the right status. And let the listSubCategory = listHomeItemResponse.toEntity(). From repository, we have the HomeItemResponse object. So this is the time we use our extension to parse response data to entity data.

UI

  • home_header.dart: Header view.
  • home_item.dart: Item of PageView.builder() in home screen
  • home_binding.dart: Injecting class for using in home screen
  • home_screen.dart: Screen UI
  • routeName is the name of this home route. It uses for navigating between screen in app.
  • StatefulWrapper: A custom widget from stateful widget. Here it is
child: GetX<HomeController>(init: controller,builder: (_) => controller.screenState == ScreenState.LOADING ? ... : ......
var _screenState = ScreenState.LOADING.obs;int get screenState => _screenState.value;

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Thế Dũng

Thế Dũng

Software engineer - Mobile developer