abstract_bloc 1.4.14 copy "abstract_bloc: ^1.4.14" to clipboard
abstract_bloc: ^1.4.14 copied to clipboard

Abstraction for fetching local or remote data via flutter_bloc

example/lib/main.dart

import 'dart:developer';

import 'package:abstract_bloc/abstract_bloc.dart';
import 'package:abstract_bloc/widgets/_all.dart';
import 'package:example/repositories/users_repository.dart';
import 'package:example/users/widgets/users_list.dart';
import 'package:flutter/material.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await RestApiClient.initFlutter();

  final restApiClient = RestApiClientImpl(
    options: RestApiClientOptions(
      baseUrl: 'https://gorest.co.in/public/v2/',
      cacheEnabled: true,
    ),
    interceptors: [
      InterceptorsWrapper(
        onRequest: (options, handler) {
          log('Logging before request');

          return handler.next(options);
        },
        onResponse: (response, handler) {
          log('Logging on response');

          return handler.next(response);
        },
        onError: (DioException e, handler) {
          log('Logging on error');

          return handler.next(e);
        },
      ),
    ],
  );
  await restApiClient.init();
  restApiClient.setContentType(Headers.jsonContentType);

  runApp(
    MultiRepositoryProvider(
      providers: [
        RepositoryProvider<RestApiClient>(create: (_) => restApiClient),
        RepositoryProvider<IUsersRepository>(
          create: (_) => UsersRepository(restApiClient: restApiClient),
        ),
      ],
      child: MaterialApp(
        title: 'Abstract Bloc Example',
        builder: (context, child) {
          //We can configure error and no-data container globally
          //so we don't have to specify it every time or have to
          //use the default one
          return AbstractConfiguration(
            loaderBuilder:
                (context) => const Center(
                  child: CircularProgressIndicator(
                    valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
                  ),
                ),
            cachedDataLoaderBuilder:
                (context) => ClipRRect(
                  borderRadius: BorderRadius.circular(50),
                  child: Container(
                    color: Colors.white.withValues(alpha: 0.5),
                    padding: const EdgeInsets.all(14.0),
                    child: const SizedBox(
                      height: 12,
                      width: 12,
                      child: CircularProgressIndicator(
                        valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
                      ),
                    ),
                  ),
                ),
            cachedDataWarningIconBuilder:
                (context, onTap) => InkWell(
                  onTap: onTap,
                  borderRadius: BorderRadius.circular(50),
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(50),
                    child: Container(
                      color: Colors.white.withValues(alpha: 0.5),
                      padding: const EdgeInsets.all(8.0),
                      child: const Icon(
                        Icons.info_outline,
                        color: Color(0xFFC42A03),
                      ),
                    ),
                  ),
                ),
            cachedDataWarningDialogBuilder:
                (context, onReload) => InfoDialog(
                  showCancelButton: true,
                  onApplyText: 'Reload',
                  onCancel: () {
                    Navigator.of(context).pop();
                  },
                  onApply: () {
                    onReload?.call(context);
                    Navigator.of(context).pop();
                  },
                  child: const Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Text(
                        'Showing cached data',
                        textAlign: TextAlign.center,
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                      SizedBox(height: 15),
                      Text(
                        'There was an error, please try again',
                        textAlign: TextAlign.center,
                      ),
                    ],
                  ),
                ),
            //This is the default implementation, you can provide your own or just ignore this parameter
            abstractItemErrorBuilder:
                (context, onInit) => Center(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Text('An error occured, please try again'),
                      const SizedBox(height: 15),
                      TextButton(
                        //This is used to re-fetch the data in case
                        //an error happens
                        onPressed: () => onInit.call(),
                        child: const Text(
                          'Reload',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      const SizedBox(height: 15),
                    ],
                  ),
                ),
            //This is the default implementation, you can provide your own or just ignore this parameter
            abstractItemNoDataBuilder:
                (context, onInit) => Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      const Text('There is no data'),
                      const SizedBox(height: 15),
                      TextButton(
                        onPressed: () => onInit.call(),
                        child: const Text(
                          'Reload',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      const SizedBox(height: 15),
                    ],
                  ),
                ),
            //This is the default implementation, you can provide your own or just ignore this parameter
            abstractListErrorBuilder:
                (context, onInit) => Center(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Text('An error occured, please try again'),
                      const SizedBox(height: 15),
                      TextButton(
                        //This is used to re-fetch the data in case
                        //an error happens
                        onPressed: () => onInit.call(),
                        child: const Text(
                          'Reload',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      const SizedBox(height: 15),
                    ],
                  ),
                ),
            //This is the default implementation, you can provide your own or just ignore this parameter
            abstractListNoDataBuilder:
                (context, onInit) => Center(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      const Text('There is no data'),
                      const SizedBox(height: 15),
                      TextButton(
                        onPressed: () => onInit.call(),
                        child: const Text(
                          'Reload',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      const SizedBox(height: 15),
                    ],
                  ),
                ),
            paginationConfiguration: PaginationConfiguration(
              initialPage: 1,
              pageSize: 10,
              toJson: (page, pageSize) => {'page': page},
            ),
            child: RefreshConfiguration(
              headerBuilder:
                  () => const ClassicHeader(
                    refreshingIcon: Loader.sm(),
                    completeText: 'Successfully refreshed',
                    refreshingText: 'Refreshing',
                    releaseText: 'Release to refresh',
                    idleText: 'Pull down to refresh',
                  ),
              footerBuilder:
                  () => ClassicFooter(
                    loadingIcon: const Loader.sm(),
                    canLoadingText: 'Release to load more',
                    loadingText: 'Loading',
                    idleText: 'Pull to load more',
                    idleIcon: Container(),
                  ),
              headerTriggerDistance: 80.0,
              springDescription: const SpringDescription(
                stiffness: 170,
                damping: 16,
                mass: 1.9,
              ),
              maxOverScrollExtent: 100,
              maxUnderScrollExtent: 0,
              enableScrollWhenRefreshCompleted: true,
              enableLoadingWhenFailed: true,
              hideFooterWhenNotFull: false,
              enableBallisticLoad: true,
              child: child!,
            ),
          );
        },
        home: const HomePage(),
      ),
    ),
  );
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Abstract Bloc Example')),
      body: const UsersList(),
    );
  }
}
7
likes
160
points
975
downloads

Publisher

unverified uploader

Weekly Downloads

Abstraction for fetching local or remote data via flutter_bloc

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

flutter, flutter_bloc, flutter_bloc_event_bus, provider, pull_to_refresh, rest_api_client

More

Packages that depend on abstract_bloc