News Reader

News Reader is simple flutter app to hit the NY Times Most Popular Articles API and show a list of articles, that shows details when items on the list are tapped (a typical master/detail app).

We’ll be using the most viewed section of this API.{section}/{period}.json?api-key=sample-key
To test this API, you can use all-sections for the section path component in the URL above and 7 for period (available period values are 1, 7 and 30, which represents how far back, in days, the API returns results for).

alt text


  • Android Studio
  • Flutter SDK 2.8.1


An API key is necessary to successfully connect to the API that the app uses. Once an API key has been aquired, change the API_KEY property in /nyt_flutter/lib/common/contant.dart and run the app.

App Architecture

This sample follows BLoC pattern + Clean Architecture.


The model is the domain object. It represents the actual data and/or information we are dealing with. An example of a model might be a contact (containing name, phone number, address, etc) or the characteristics of a live streaming publishing point.

The key to remember with the model is that it holds the information, but not behaviors or services that manipulate the information. It is not responsible for formatting text to look pretty on the screen, or fetching a list of items from a remote server (in fact, in that list, each item would most likely be a model of its own). Business logic is typically kept separate from the model, and encapsulated in other classes that act on the model.

Data layer

Provides all required data to the repository in form of models/entities.

Remote data source

Manage all server/external API calls.

Local data source

Manage all local data storage: example SQLite implementation, Room, Realm…


The decision maker class when it comes to manage data CRUD operations. Operations can be done in this layer is caching mechanism, manage consecutive api calls etc…


Represents concepts of the business, information about the current situation and business rules.


There are three primary gadgets in the BLoC library:

  • Bloc
  • BlocBuilder
  • BlocProvider
    You’ll require them to set up BLoCs, construct those BLoCs as indicated by the progressions in the app’s state, and set up conditions. How about we perceive how to execute every gadget and use it in your app’s business rationale.

The Bloc gadget is the fundamental segment you’ll have to execute all business rationale. To utilize it, expand the Bloc class and supersede the mapEventToState and initialState techniques.


BlocBuilder is a gadget that reacts to new states by building BLoCs. This gadget can be called on numerous occasions and acts like a capacity that reacts to changes in the state by making gadgets that appear new UI components.


This gadget fills in as a reliance infusion, which means it can give BLoCs to a few gadgets all at once that have a place with the equivalent subtree. BlocProvider is utilized to construct blocs that will be accessible for all gadgets in the subtree.

Getting Started

This repository implements the following quality gates:

Build Pipeline

  • Static code checks: running lint to check the code for any issues.
  • Unit testing: running the unit tests
  • Code coverage: generating code coverage reports using the LCOV
  • Integration testing: running the functional tests using Flutter Integration Testing

These steps can be run manually or using a Continous Integration tool such as Bitrise.

Checkout the Code

Checkout and run the code

git clone

Major Libraries / Tools

Category Library/Tool Link
Development Flutter – Dart
IDE Android Studio
Unit Testing Flutter Unit Test
Code Coverage LCOV
Static Code Check Lint for Dart/Flutter
Integration Testing Flutter Integration Testing
CI/CD Bitrise
Dependency Injection injectable
Service Locator get_it
Presentation Layer Mangement flutter_bloc
Network Layer Mangement retrofit
Code Generator Freezed
HTTP Client Dio
Image Caching cached_network_image
Mock Library Mockito

Setting up Prerequisites

Install LCOV

Run the following command in terminal sudo apt-get install lcov

Install scrcpy

Run the following command in terminal sudo apt install scrcpy

Generate files

Run the following command in terminal flutter pub run build_runner watch --delete-conflicting-outputs

Running Quality Gates and Deployment Commands


Run the following command in terminal flutter analyze
alt text


Tests in Flutter are separated into 2 types:


Located at /test – These are tests that run on your machine. Use these tests to minimize execution time when your tests have no flutter framework dependencies or when you can mock the flutter framework dependencies.
alt text

Integration tests

Located at /integration_test – These are tests that run on a hardware device or emulator. These tests have access to all flutter APIs, give you access to information such as the Context of the app you are testing, and let you control the app under test from your test code. Use these tests when writing integration and functional UI tests to automate user interaction, or when your tests have flutter dependencies that mock objects cannot satisfy.
alt text
alt text

Running the Unit Tests

Unit testing for Flutter applications is fully explained in the Flutter documentation. In this repository,
From Android Studio

  • Right Clicking on the Class and select “Run
  • To see the coverage we have t the select “Run with Coverage”

Test Coverage

The test coverage uses the LCOV library
In order to run both test and integration_test and generate a code coverage report, create a script file to do the job.

red=$(tput setaf 1)  
none=$(tput sgr0)  
show_help() {  
    printf "  
Script for running all unit and widget tests with code coverage.  
(run it from your root Flutter's project)  
*Important: requires lcov  
 $0 [--help] [--open] [--filename <path>]where:  
 -o, --open Open the coverage in your browser, Default is google-chrome you can change this in the function open_cov(). -h, --help print this message -f <path>, --filename <path> Run a particular test file. For example:             -f test/a_particular_test.dart  
         Or you can run all tests in a directory  
 -f test/some_directory/"  
run_tests() {  
    if [[ -f "pubspec.yaml" ]]; then  
  rm -f coverage/  
        rm -f coverage/  
        flutter test --coverage "$filename"  
  printf "\n${red}Error: this is not a Flutter project${none}\n"  
  exit 1  
run_report() {  
    if [[ -f "coverage/" ]]; then  
  lcov -r coverage/ lib/resources/l10n/\* lib/\*/fake_\*.dart \  
             -o coverage/  
        genhtml -o coverage coverage/  
  printf "\n${red}Error: no coverage info was generated${none}\n"  
  exit 1  
  echo "$input"  
  while read line  
  echo "${line/SF:/$secondString}" >> $output  
    done < "$input"  
  mv $output $input  
    # This depends on your system   
    # Google Chrome:  
 # google-chrome coverage/index-sort-l.html # Mozilla:  firefox coverage/index-sort-l.html  
while [ "$1" != "" ]; do  
 case $1 in  
 exit  ;;  
 exit  ;;  
 esac  shift  
remove_from_coverage -f coverage/ -r '.g.dart$'  
remove_from_coverage -f coverage/ -r '.freezed.dart$'  
remove_from_coverage -f coverage/ -r '.config.dart$'  
if [ "$open_browser" = "1" ]; then  

Below lines are added to ignore the generated files when generating the code coverage report:

remove_from_coverage -f coverage/ -r '.g.dart$'  
remove_from_coverage -f coverage/ -r '.freezed.dart$'  
remove_from_coverage -f coverage/ -r '.config.dart$' 

From the commandline


Test coverage results are available at

alt text

CI-CD – Build via Bitrise (yml file)

This repo contains a bitrise, which is used to define a Bitrise declarative pipeline for CI-CD to build the code, run the quality gates, code coverage, static analysis and deploy to Bitrise.

Here is the structure of the bitrise declarative pipeline:

format_version: '11'  
default_step_lib_source: ''  
project_type: flutter  
- push_branch: '*'  
  workflow: primary  
- pull_request_source_branch: '*'  
  workflow: primary  
    - activate-ssh-key@4:  
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'  
  - git-clone@6: {}  
    - script@1:  
        title: Do anything with Script step  
    - certificate-and-profile-installer@1: {}  
    - flutter-installer@0:  
        - is_update: 'false'  
  - cache-pull@2: {}  
    - flutter-analyze@0:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - flutter-test@1:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - flutter-build@0:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
        - platform: both  
    - xcode-archive@4:  
        - project_path: $BITRISE_PROJECT_PATH  
        - scheme: $BITRISE_SCHEME  
        - distribution_method: $BITRISE_DISTRIBUTION_METHOD  
        - configuration: Release  
    - deploy-to-bitrise-io@2: {}  
    - cache-push@2: {}  
    - activate-ssh-key@4:  
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'  
  - git-clone@6: {}  
    - script@1:  
        title: Do anything with Script step  
    - flutter-installer@0:  
        - is_update: 'false'  
  - cache-pull@2: {}  
    - [email protected]:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - flutter-test@1:  
        - project_location: $BITRISE_FLUTTER_PROJECT_LOCATION  
    - deploy-to-bitrise-io@2: {}  
    - cache-push@2: {}  
    stack: linux-docker-android-20.04  
    machine_type_id: elite  
  - opts:  
      is_expand: false  
  - opts:  
      is_expand: false  
  - opts:  
      is_expand: false  
  - opts:  
      is_expand: false  

Below is an illustration of the pipeline that Bitrise will execute

alt text

Building the application using Bitrise

These steps should be followed to automated the app build using Bitrise:

  • Create an account on Bitrise.
  • Follow the wizard for creating a Flutter project on Bitrise.
  • In workflows tab, and select <>bitrise.yaml tab.
  • Choose Store in app repository to read the repository yaml file.

This repository already attached to a public bitrise project.


Apache License, Version 2.0


View Github