Given a list of contact names (as
List<String>
for demo purposes), render an address book list where the names are grouped by their first character.
- Implementation should be done in its own Widget
- We expect a
GroupedListView
widget which receives the items - Make this widget generic and be able to work with any data type, given the appropriate builder is provided
- It should be a single, continuous list widget
- Preferably this scroll view should be using
Slivers
and aCustomScrollView
- Preferably this scroll view should be using
- In the end, all data should be displayed in one continuous scrolling list
- Only visible items should be rendered (expect huge amounts of test data and a requirement to show images next to each contact)
- We expect a
- Use any styling you want, stock Material widgets are fine
- Only show groups that have entries
- Each entry should be tappable (next screen may just show the name in "detail view"
- There should be the ability to show widgets on the top and below the list
- For this challenge, we only want to inject a vertical list of buttons
- A search field should be provided to filter down the list
- When a search is active, the additional widgets should be hidden
- Describe why a Scroll to index API is not as straightforward with normal
ListView
orSliver
widgets in the README of the project - Please finish your coding challenge with a short README outlining your thinking behind the implementation and any open issues you would want to explore if there were more time.
The app's primary goal is to display a list of contacts provided by either a local or remote data source. Users also have the ability to search for specific contacts from the list or tap on tiles to access further information.
The graphical user interface and experience were tailored with the Material design system in mind. Rather than adapting interface components to each platform's native look, a customized app theme was created to convey a unified look and feel of the product's brand. Certain platform-defining characteristics were preserved (e.g. back button icons and transitions).
“It is not enough for code to work.”
As uncle Bob said, even bad code can function. To make sure it is also clean, this project's code is divided into four layers: Presentation
, Business Logic
, Repository
, and Data Source
.
- Presentation layer => Contains reactive widgets which draw visual components to the screen (e.g.
MyContactTile
). - Business Logic => Is implemented via the BLoC design pattern, where a middleware listens to streams of events and output states mapped according to some business logic.
- Repository => Encapsualtes data access logic and exposes a single source of truth. Data can be retrieved from either a local or remote source.
- Data Source => Persistence or networking logic to retrieve data.
Dependency | Version | Category | Purpose |
---|---|---|---|
cupertino_icons | ^0.1.3 | UI | use iOS icons |
sticky_and_expandable_list | ^0.2.1 | UI | improve the experience with a persistent list section header on scroll |
with_bloc | ^2.0.0 | State management | use AY tech and facilitate injection of blocs |
state_queue | ^2.0.0 | State management | use AY tech and faciliate the flow of streams |
url_launcher | ^5.5.0 | Capability | send the user to an external url on the browser |
equatable | ^1.2.4 | Capability | facilitate the comparison between objects |
Notes:
- Only the 'sticky' functionality provided by
sticky_and_expandable_list
is used. This project drifts a bit away from the basic use-case because theCustomScrollView
is nested inside aNestedScrollView
. with_bloc
andstate_queue
were chosen because they are in-house depencies used by About You to handle state management. An alternative library would be felangel`s bloc.- Redux was not chosen for state management because it requires far more boilerplate code and the application scope is minimal. Redux would be more adequate in large-scale projects with 6+ developers. Personally, I prefer to distribute the application state according to its relevant scope instead of concentrating everything in a global store.
- Layered architecture; presentation detached from business logic
- Use of BLoCs for state management
- Single source of truth for fetching data via the repository pattern
- In-memory cache simulating local storage persistence
- Remote data source simulation
- Route declaration and dependency injection via the
RouteProvider
- Lazy loading widgets when scroll through conent
- Separation of the app bar widget by using a
NestedScrollView
- Support for
header
andfooter
slivers in theGroupedListView
- Users get visual feedback for
progress
,error
, andsuccess
states - App theming via
AppTheme
andStyles
- Data sanitization
- Search capabilities with real-time suggestions
- The UI is compatible with any smartphone screen size and orientation
- Thorough documentation
- Unit tested
- Localized (en, de, pt, es)
- Dark mode
Describe why a Scroll to index API is not as straightforward with normal ListView or Sliver widgets in the README of the project
In Flutter, scroll to index is not as straightforward with ListView
or Slivers
because these widgets may contain items with distinct measures. Moreover, these items are usually lazy loaded, which means they won't be rendered until they are 200 pixels close from the active viewport.
This issue is widely discussed by community members in flutter's repo. Some alternatives to achieving scrollToIndex
are:
- Replacing the
ListView
with aSingleChilScrollView
and wrapping the children into aColumn
-- only for pre-defined and small lists. More details here. - Incorporate the
scrollable_positioned_list
library published by google. Keep in mind This is not an officially supported Google product.
This project requires flutter to be installed in your machine. If you don't already have it, please follow this amazing official guide. Once you have flutter, all you need to do is:
- Open an Android or iOS simulator
- Clone this repo to somewhere in your machine (Let's say...
myProjectFolder
) - Go to you
myProjectFolder
, then go to the challenge's folder
cd ay_flutter_challenge
- Run the project!
flutter run
Thanks for the challenge! It's been a lot of fun