- lib
- config
- routes
- theme
- core
- constants
- error
- network
- resources
- usecases
- utils
- fetures
- sample
- data
- data_sources
- models
- repository
- domain
- entities
- repository
- usecases
- presentation
- bloc
- pages
- injection_container.dart
- main.dart
pubspec.yaml
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
#flutter bloc
flutter_bloc: ^8.1.2
#comparing dart objects
equatable: ^2.0.5
#service locator
get_it: ^7.6.0
#dateFormatter
intl: ^0.18.1
#Databse
floor: ^1.4.2
#hooks
flutter_hooks: ^0.18.3
#chached image
cached_network_image: ^3.2.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
retrofit_generator: ^3.0.1+1
floor_generator: 1.2.0
build_runner: 2.1.2
flutter:
flutter_lints: ^2.0.0
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
fonts:
- family: Muli
fonts:
- asset: assets/fonts/muli/Muli.ttf
- asset: assets/fonts/muli/Muli-Bold.ttf
weight: 700
- asset: assets/fonts/muli/Muli-Light.ttf
weight: 300
- presentaion
- bloc
- article
- remote
- remote_article_bloc.dart
- remote_article_event.dart
- remote_article_state.dart
- pages
- home
- daily_news.dart
- widgets
- article_tile.dart
lib/fetures/daily_news/presentaion/pages/home/daily_news.dart
_buildBody() {
return BlocBuilder<RemoteArticlesBloc, RemoteArticlesState>(
builder: (_, state) {
if (state is RemoteArticlesLoading) {
return const Center(
child: CupertinoActivityIndicator(),
);
}
if (state is RemoteArticlesError) {
return const Center(
child: Icon(Icons.refresh),
);
}
if (state is RemoteArticlesDone) {
return ListView.builder(
itemBuilder: (contex, index) {
return ArticleWidget(article: state.articles![index]);
},
itemCount: state.articles!.length,
);
}
return const SizedBox();
},
);
lib/fetures/daily_news/presentaion/bloc/article/remote/remote_article_state.dart
abstract class RemoteArticlesState extends Equatable {
final List<ArticleEntity>? articles;
final DioException? error;
const RemoteArticlesState({this.articles, this.error});
@override
List<Object> get props => [articles!, error!];
}
class RemoteArticlesLoading extends RemoteArticlesState {
const RemoteArticlesLoading();
}
class RemoteArticlesDone extends RemoteArticlesState {
const RemoteArticlesDone(List<ArticleEntity> articles) : super(articles: articles);
}
class RemoteArticlesError extends RemoteArticlesState {
const RemoteArticlesError(DioException error) : super(error: error);
}
lib/fetures/daily_news/presentaion/bloc/article/remote/remote_article_event.dart
abstract class RemoteArticlesEvent {
const RemoteArticlesEvent();
}
class GetArticles extends RemoteArticlesEvent {
const GetArticles();
}
lib/fetures/daily_news/presentaion/bloc/article/remote/remote_article_bloc.dart
class RemoteArticlesBloc extends Bloc<RemoteArticlesEvent, RemoteArticlesState> {
final GetArticleUseCase _getArticleUseCase;
RemoteArticlesBloc(this._getArticleUseCase) : super(const RemoteArticlesLoading()) {
on <GetArticles> (onGetArticles);
}
void onGetArticles(GetArticles event, Emitter<RemoteArticlesState> emitter) async {
final datastate = await _getArticleUseCase();
if (datastate is DataSuccess && datastate.data!.isNotEmpty) {
emit(
RemoteArticlesDone(datastate.data!)
);
}
if (datastate is DataFailed) {
print(datastate.error!.message);
emit(
RemoteArticlesError(datastate.error!)
);
}
}
}
- domain
- entities
- article.dart
- repository
- article_repository.dart
- usercases
- get_article.dart
lib/fetures/daily_news/domain/entities/article.dart
import 'package:equatable/equatable.dart';
class ArticleEntity extends Equatable {
final int? id;
final String? author;
final String? title;
final String? description;
final String? url;
final String? urlToImage;
final String? publishedAt;
final String? content;
const ArticleEntity({
this.id,
this.author,
this.title,
this.description,
this.url,
this.urlToImage,
this.publishedAt,
this.content,
});
@override
List<Object?> get props {
return [
id,
author,
title,
description,
url,
urlToImage,
publishedAt,
content,
];
}
}
lib/fetures/daily_news/domain/repository/article_repository.dart
abstract class ArticleRepository {
Future<DataState<List<ArticleEntity>>> getNewsArticles();
}
lib/fetures/daily_news/domain/usercases/get_article.dart
class GetArticleUseCase implements UseCase<DataState<List<ArticleEntity>>, void> {
final ArticleRepository _repository;
GetArticleUseCase(this._repository);
@override
Future<DataState<List<ArticleEntity>>> call({void params}) {
return _repository.getNewsArticles();
}
}
- data
- data_soures
- local
- DAO
- article_dao.dart
- app_database.dart
- app_database.g.dart
lib/fetures/daily_news/data/data_soures/local/DAO/article_dao.dart
import 'package:floor/floor.dart';
import '../../../models/article.dart';
@dao
abstract class ArticleDao {
@Insert()
Future<void> insertArticle(ArticleModel article);
@delete
Future<void> deleteArticle(ArticleModel articleModel);
@Query('SELECT * FROM article')
Future<List<ArticleModel>> getArticles();
}
lib/fetures/daily_news/data/data_soures/local/app_database.dart
import 'dart:async';
import 'package:floor/floor.dart';
import 'package:sqflite/sqflite.dart' as sqflite;
import '../../models/article.dart';
import 'DAO/article_dao.dart';
part 'app_database.g.dart';
@Database(version: 1, entities: [ArticleModel])
abstract class AppDatabse extends FloorDatabase {
ArticleDao get articleDao;
}
lib/injection_container.dart
final s1 = GetIt.instance;
Future<void> initialaizeDependencies() async {
final database = await $FloorAppDatabse.databaseBuilder('app_database.db').build();
s1.registerSingleton<AppDatabse>(database);
lib/fetures/daily_news/domain/usercases/get_saved_article.dart
import '../repository/article_repository.dart';
class GetSavedArticleUseCase implements UseCase<List<ArticleEntity>, void> {
final ArticleRepository _repository;
GetSavedArticleUseCase(this._repository);
@override
Future<List<ArticleEntity>> call({void params}) {
return _repository.getSavedArticles();
}
}
lib/fetures/daily_news/domain/usercases/remove_article.dart
import '../repository/article_repository.dart';
class RemoveArticleUseCase implements UseCase<void, ArticleEntity> {
final ArticleRepository _repository;
RemoveArticleUseCase(this._repository);
@override
Future<void> call({ArticleEntity? params}) {
return _repository.deleteArticle(params!);
}
}
lib/fetures/daily_news/domain/usercases/save _article.dart
class SavedArticleUseCase implements UseCase<void, ArticleEntity> {
final ArticleRepository _repository;
SavedArticleUseCase(this._repository);
@override
Future<void> call({ArticleEntity? params}) {
return _repository.saveArticle(params!);
}
}
lib/injection_container.dart
s1.registerSingleton<GetSavedArticleUseCase>(
GetSavedArticleUseCase(s1())
);
s1.registerSingleton<SavedArticleUseCase>(
SavedArticleUseCase(s1())
);
s1.registerSingleton<RemoveArticleUseCase>(
RemoveArticleUseCase(s1())
);
IF not using DI
Api api = Api(clinet: Client());
class Api {
Client clinet;
Api({this.client})
}
class HomeScreen extends StatelessWidget {
Api api;
HomeScreen({this.api})
}
HomeScreen(api: Api(clent: Clent());
If using DI lib/injection_container.dart
final sl = GetIt.instance;
Future<void> initialaizeDependencies() async {
final database = await $FloorAppDatabse.databaseBuilder('app_database.db').build();
sl.registerSingleton<AppDatabse>(database);
// Dio
sl.registerSingleton<Dio>(Dio());
// Dependencies
sl.registerSingleton<NewsApiService>(NewsApiService(sl()));
sl.registerSingleton<ArticleRepository>(
ArticleRepositoryImpl(sl(), sl())
);
// UseCases
sl.registerSingleton<GetArticleUseCase>(GetArticleUseCase(sl()));
sl.registerSingleton<GetSavedArticleUseCase>(
GetSavedArticleUseCase(sl())
);
sl.registerSingleton<SavedArticleUseCase>(
SavedArticleUseCase(sl())
);
sl.registerSingleton<RemoveArticleUseCase>(
RemoveArticleUseCase(sl())
);
// Blocs
sl.registerFactory<RemoteArticlesBloc>(
()=> RemoteArticlesBloc(sl())
);
sl.registerFactory<LocalArticleBloc>(
()=> LocalArticleBloc(sl(), sl(), sl())
);
}
main.dart
void main() async
await initialaizeDependencies();
runApp(const MyApp());
}