#flutter #flutter-bloc
#flutter #flutter-блок
Вопрос:
Я пытаюсь создать приложение для фильмов с блочной и чистой архитектурой, я хочу показывать популярные фильмы и фильмы с самым высоким рейтингом, однако я могу показать только один из них. Я использую один и тот же блок для обоих вариантов использования.
Что я делаю не так?, должен ли я использовать два блока?
Я опубликую некоторый код, однако вот полная демонстрация https://github.com/DavidAriza/MoviesApp . Заранее спасибо
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:prueba_gbp/presentation/blocs/home_bloc/home_cubit.dart';
import 'package:prueba_gbp/presentation/screens/home_screen.dart';
import 'injection_container.dart' as di;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await di.init();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => di.sl<HomeCubit>()..getPopularMovies()..getTopRatedMovies(),
child: MaterialApp(
home: HomeScreen(),
),
);
}
}
home_cubit.dart
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:prueba_gbp/domain/entities/movie_entity.dart';
import 'package:prueba_gbp/domain/usecases/get_populares_movies.dart';
import 'package:prueba_gbp/domain/usecases/get_top_rated_movies.dart';
part 'home_state.dart';
class HomeCubit extends Cubit<HomeState> {
final GetPopularesMoviesUseCase getPopularesMoviesUseCase;
final GetTopRatedMoviesUseCase getTopRatedMoviesUseCase;
HomeCubit({this.getPopularesMoviesUseCase, this.getTopRatedMoviesUseCase})
: super(MoviesInitial());
Future<void> getPopularMovies() async {
try {
emit(MoviesLoadingState());
final popularMovies = await getPopularesMoviesUseCase.call();
emit(PopularesMoviesLoadedState(popularMovies));
} catch (e) {
print(e);
}
}
Future<void> getTopRatedMovies() async {
try {
emit(MoviesLoadingState());
final topRatedMovies = await getTopRatedMoviesUseCase.call();
emit(TopRatedMoviesLoadedState(topRatedMovies));
} catch (e) {
print(e);
}
}
}
home_state.dart
part of 'home_cubit.dart';
abstract class HomeState extends Equatable {
const HomeState();
}
class MoviesInitial extends HomeState {
const MoviesInitial();
@override
// TODO: implement props
List<Object> get props => throw UnimplementedError();
}
class MoviesLoadingState extends HomeState{
@override
List<Object> get props => [];
}
class PopularesMoviesLoadedState extends HomeState{
final List<MovieEntity> popularesMovies;
PopularesMoviesLoadedState(this.popularesMovies);
@override
List<Object> get props => [popularesMovies];
}
class TopRatedMoviesLoadedState extends HomeState{
final List<MovieEntity> topRatedMovies;
TopRatedMoviesLoadedState(this.topRatedMovies);
@override
List<Object> get props => [topRatedMovies];
}
injection_container.dart
import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:prueba_gbp/data/data_source/movies_remote_data_source.dart';
import 'package:prueba_gbp/data/data_source/movies_remote_data_source_impl.dart';
import 'package:prueba_gbp/data/repositories/movies_repository_impl.dart';
import 'package:prueba_gbp/domain/repositories/movies_repository.dart';
import 'package:prueba_gbp/domain/usecases/get_populares_movies.dart';
import 'package:prueba_gbp/domain/usecases/get_top_rated_movies.dart';
import 'package:prueba_gbp/presentation/blocs/home_bloc/home_cubit.dart';
final sl = GetIt.instance;
Future<void> init() async {
//Futures bloc
sl.registerFactory<HomeCubit>(() => HomeCubit(
getPopularesMoviesUseCase: sl.call(),
getTopRatedMoviesUseCase: sl.call()
));
//use cases
sl.registerLazySingleton<GetPopularesMoviesUseCase>(() => GetPopularesMoviesUseCase(repository: sl.call()));
sl.registerLazySingleton<GetTopRatedMoviesUseCase>(() => GetTopRatedMoviesUseCase(repository: sl.call()));
//repository
sl.registerLazySingleton<MoviesRepository>(() => MoviesRepositoryImpl(remoteDataSource: sl.call()));
//remote data
sl.registerLazySingleton<MoviesRemoteDataSource>(() => MoviesRemoteDataSourceImpl(client: sl.call()));
//external
sl.registerLazySingleton(() => http.Client());
}
home_screen.dart
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: Colors.blue[200],
body: SingleChildScrollView(
child: _buildBody(size, context)
),
);
}
_buildBody(Size size, BuildContext context, ) {
return Column(
children: [
SizedBox(
height: size.height,
child: Stack(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
height: size.height*0.7,
width: double.infinity,
margin: EdgeInsets.only(top: size.height*0.3),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24),
topRight: Radius.circular(24),
)
),
child: Column(
children: [
SizedBox(height: 10.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'POPULARES',
style: TextStyle(
fontWeight: FontWeight.bold
),
),
Text(
'See all'
),
],
),
SizedBox(height: 10.0),
BlocBuilder<HomeCubit, HomeState>(
builder: (_, currentState) {
if(currentState is MoviesLoadingState) {
return CircularProgressIndicator();
}
else if (currentState is PopularesMoviesLoadedState )
return MovieHorizontal(peliculas: currentState.popularesMovies);
else {
return CircularProgressIndicator();
}
}
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'TOP RATED',
style: TextStyle(
fontWeight: FontWeight.bold
),
),
Text(
'See all'
),
],
),
SizedBox(height: 10),
BlocBuilder<HomeCubit, HomeState>(
builder: (_, currentState){
if(currentState is MoviesLoadingState) {
return CircularProgressIndicator();
}
else if (currentState is TopRatedMoviesLoadedState )
return MovieHorizontal(peliculas: currentState.topRatedMovies);
else {
return CircularProgressIndicator();
}
}
)
],
),
),
Padding(
padding: const EdgeInsets.only(right: 23.0, left: 23.0, top: 80.0),
child: Column(
children: [
Text(
'Hello, what do you nwant to watch?',
style: TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold
),
),
SizedBox(height: 10.0),
TextField(
style: TextStyle(color: Colors.white),
decoration: InputDecoration(
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
prefixIcon: Icon(Icons.search),
hintText: "Search",
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white, width: 32.0),
borderRadius: BorderRadius.circular(25.0)
),
)
)
],
),
)
],
)
)
],
);
}
}
Комментарии:
1. вы даже можете использовать один блок для всего вашего приложения, но это может сбить вас с толку в будущем, поэтому лучше их классифицировать
Ответ №1:
Для сохранения более модульного кода и для улучшения улучшений в будущем будет лучше создать два разных блока, чтобы уменьшить сложность