full_context 1.1.1 copy "full_context: ^1.1.1" to clipboard
full_context: ^1.1.1 copied to clipboard

Intuitive state management via Context. With FullContext you still need Providers and Builders to instantiate and display states, but management can all be done through Context

example/lib/main.dart

import 'dart:async';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:full_context/full_context.dart';

void main() {
  runApp(App());
}

abstract class EntityBase {
  Map<String, dynamic> toMap();
}

class Entity implements EntityBase {
  final int id;
  final String name;

  Entity({required this.id, required this.name});

  factory Entity.fromMap(Map<String, dynamic> map) {
    return Entity(
      id: map['id'],
      name: map['name'],
    );
  }

  Entity copyWith({
    int? id,
    String? name,
  }) {
    return Entity(
      id: id ?? this.id,
      name: name ?? this.name,
    );
  }

  @override
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
    };
  }
}

class Dal {
  Dal(this.db);

  final Database db;

  Future<int> insert<T extends EntityBase>(T entity) {
    return db.insert(
      '$T',
      entity.toMap(),
      conflictAlgorithm: ConflictAlgorithm.replace,
    );
  }

  Future<Iterable<T>> getAll<T>(
    T Function(Map<String, dynamic> map) fromMap,
  ) async {
    final rows = await db.rawQuery('SELECT * FROM $T');
    final entities = rows.map(fromMap);
    return entities;
  }
}

class Repository {
  Repository(this.dal);

  final Dal dal;

  Future<int> insert(Entity entity) => dal.insert(entity);
  Future<Iterable<Entity>> getAll() => dal.getAll(Entity.fromMap);
}

class Service {
  Service(this.repository);

  final Repository repository;

  Future<Iterable<Entity>> getAll() => repository.getAll();
  Future<int> insert(Entity entity) => repository.insert(entity);
}

class Controller {
  Controller(this.service);

  final Service service;

  Future<List<Entity>> getAll() async {
    final entities = await service.getAll();
    return entities.toList();
  }

  Future<void> insert(BuildContext context) async {
    final entities = await service.getAll();
    final enity = entities.last;
    final newEntity = enity.copyWith(id: enity.id + 1);
    await service.insert(newEntity);
    final newEntities = await service.getAll();
    if (!context.mounted) return;

    return context.emit(newEntities.toList());
  }
}

class App extends StatelessWidget {
  App({super.key});

  Future<void> _onCreate(Database db, int version) async {
    await db.execute(
      'CREATE TABLE $Entity (id INTEGER PRIMARY KEY, name TEXT)',
    );

    final entity = Entity(id: 1, name: 'Hello World!');
    await db.insert('$Entity', entity.toMap());
  }

  late final factories = [
    () => 1,
    getDatabasesPath,
    (List<GoRoute> routes) => GoRouter(routes: routes, initialLocation: '/'),
    () => [GoRoute(path: '/', builder: (context, state) => Home())],
    (String databasesPath, int version) {
      String path = join(databasesPath, 'demo.db');
      return openDatabase(
        path,
        version: version,
        onCreate: _onCreate,
      );
    }
  ];

  @override
  Widget build(BuildContext context) {
    return FullContext(
      factories: factories,
      listenables: [Database],
      loadingBuilder: (context) => const AppLoading(),
      errorBuilder: (context, error) => AppError(error: error.toString()),
      builder: (context) => MaterialApp.router(
        routerConfig: context.get<GoRouter>(),
        builder: (context, child) => child!,
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(child: CircularProgressIndicator()),
      ),
    );
  }
}

class AppError extends StatelessWidget {
  const AppError({super.key, required this.error});

  final String error;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: Text(error)),
      ),
    );
  }
}

class Home extends StatelessWidget {
  Home({super.key});

  final factories = [
    Dal.new,
    Service.new,
    Controller.new,
    Repository.new,
    (Controller controller) => controller.getAll()
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('FullContext Example')),
      body: FullContext(
        factories: factories,
        listenables: [List<Entity>],
        loadingBuilder: (context) => const Center(
          child: CircularProgressIndicator(),
        ),
        errorBuilder: (context, error) => Center(child: Text('Error: $error')),
        builder: (context) {
          final entities = context.get<List<Entity>>();
          final controller = context.get<Controller>();

          return InkWell(
            onTap: () => controller.insert(context),
            child: ListView.separated(
              itemCount: entities.length,
              separatorBuilder: (context, index) => const Divider(),
              itemBuilder: (context, index) {
                final entity = entities[index];
                return ListTile(
                  title: Text('ID: ${entity.id}'),
                  subtitle: Text('Name: ${entity.name}'),
                );
              },
            ),
          );
        },
      ),
    );
  }
}
2
likes
160
points
180
downloads

Publisher

unverified uploader

Weekly Downloads

Intuitive state management via Context. With FullContext you still need Providers and Builders to instantiate and display states, but management can all be done through Context

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, rxdart

More

Packages that depend on full_context