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
confighandle environment flavorexceptionclass to handle internet exceptionfailureclass to handle failureusecaseblue print of usecasesvaluestype data hard coderepositoriesafter repo domain created then extends the repositories in here.datasourcedesign pattern that is used to abstract the data access logic from the rest of the application.modelsused 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: