Data Layer¶
The core business entities and their relationships are defined, which is the heart of the application. It's also the layer that defines the use cases of the application.
To follow this step you have to understand :
Structure
config
handle environment flavorexception
class to handle internet exceptionfailure
class to handle failureusecase
blue print of usecasesvalues
type data hard coderepositories
after repo domain created then extends the repositories in here.datasource
design pattern that is used to abstract the data access logic from the rest of the application.models
used to represent the data that is used by the application.
1. Create Remote Datasource¶
abstract class UserRemoteDatasource {
Future<List<UserEntity>> getUserData(UserParamsEntity params);
}
class UserRemoteDatasourceImpl implements UserRemoteDatasource {
final BaseApi baseApi;
UserRemoteDatasourceImpl(this.baseApi);
@override
Future<List<UserEntity>> getUserData(UserParamsEntity params) async {
final data = await baseApi.get(USERS, queryParameters: {'_start': params.start, '_limit': params.limit});
return (data as Iterable).map<UserModel>((value) => UserModel.fromJson(value)).toList();
}
}
Info
After class BaseApi
register on injection.dart
2. Crate Local Datasource¶
import 'package:hive/hive.dart';
import 'package:solid_data/solid_data.dart';
abstract class UserLocalDatasource {
Future<List<UserModel>> getUsersFromCache();
Future<void> usersToCache(List<UserModel> params);
Future<void> usersDeleteCache();
}
class UserLocalDatasourceImpl implements UserLocalDatasource {
Future<Box> _getBox() async {
return await Hive.openBox(BOX_KEY_USERS).onError((e, s) => throw CacheException());
}
@override
Future<List<UserModel>> getUsersFromCache() async {
Box box = await _getBox();
try {
if (box.containsKey(BOX_KEY_USERS)) {
List<dynamic> data = await box.get(BOX_KEY_USERS);
return data.map((e) => e as UserModel).toList();
} else {
throw CacheException(message: EXCEPTION_UNKNOWN);
}
} catch (e) {
throw CacheException();
}
}
@override
Future<void> usersToCache(List<UserModel> params) async {
Box box = await _getBox();
List<UserModel> local = await box.get(BOX_KEY_USERS) ?? [];
local.addAll(params);
box.put(BOX_KEY_USERS, local).onError((e, s) => throw CacheException());
}
@override
Future<void> usersDeleteCache() async {
Box box = await _getBox();
print('Users cache has been deleted');
box.delete(BOX_KEY_USERS).onError((e, s) => throw CacheException());
}
}
3. Implement repositories¶
class UserRepositoryImpl extends UserRepository {
final UserRemoteDatasource remoteDatasource;
final UserLocalDatasource localDatasource;
final NetworkInfo networkInfo;
UserRepositoryImpl({
required this.remoteDatasource,
required this.localDatasource,
required this.networkInfo,
});
@override
Future<Either<Failure, List<UserEntity>>> getUserData(UserParamsEntity params) async {
return _checkUserCache(
() {
try {
return remoteDatasource.getUserData(params);
} catch (e) {
if (e is ServerException) {
return Left(ServerFailure(message: e.message));
} else {
return Left(UnknownFailure(message: FAILURE_UNKNOWN));
}
}
},
isInit: params.isInit,
);
}
Future<Either<Failure, List<UserModel>>> _checkUserCache(Function() getUsers, {required bool isInit}) async {
try {
if (await networkInfo.isConnected) {
if (isInit) {
localDatasource.usersDeleteCache();
}
final getUsersRemote = await getUsers();
localDatasource.usersToCache(getUsersRemote);
return Right(getUsersRemote);
} else {
List<UserModel> localData = await localDatasource.getUsersFromCache();
return Right(localData);
}
} catch (e) {
if (e is CacheException) {
return Left(CacheFailure(message: e.message));
} else {
return Left(UnknownFailure(message: FAILURE_UNKNOWN));
}
}
}
}
4. Register to Dependancy Injection¶
After class UserRepositoryImpl
make sure UserRemoteDatasource
, UserLocalDatasource
, NetworkInfo
register on injection.dart
in Feature Layer
.
// Datasource
sl.registerLazySingleton<UserRemoteDatasource>(() => UserRemoteDatasourceImpl(sl()));
sl.registerLazySingleton<UserLocalDatasource>(() => UserLocalDatasourceImpl());
// RepositoryImpl
sl.registerLazySingleton<UserRepository>(
() => UserRepositoryImpl(
remoteDatasource: sl(),
localDatasource: sl(),
networkInfo: sl(),
),
);
For more information injectable.
Authors: