Как правильно использовать блок с двумя событиями для одного и того же экрана?

#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)
                      ),
                    )
                  )
                ],
              ),
            )
          ],
        )
      )
    ],
    );
  }
}
  

2

Комментарии:

1. вы даже можете использовать один блок для всего вашего приложения, но это может сбить вас с толку в будущем, поэтому лучше их классифицировать

Ответ №1:

Для сохранения более модульного кода и для улучшения улучшений в будущем будет лучше создать два разных блока, чтобы уменьшить сложность