Home > Net >  Dart Inherit class and Use it in functions of the parent class
Dart Inherit class and Use it in functions of the parent class

Time:06-25

I want to make a parent class which use ChangeNotifier. And from this class, I want to create two separate inherited classes that will provide list data to some parts of the app, and each will have its own separate list. But I could not figure out how each class could create its own list and only make operations on that list via using superclass. Can someone explain to me how can I manage this?

import 'package:flutter/material.dart';

class ObjectListProvider<T extends num, K extends Object> with ChangeNotifier {
  final Map<T, K> _map = {};

  Map<T, K> get map {
    return {..._map};
  }

  K? getSingleObjectWithId(id) {
    return _map[id];
  }

  void add(T id, K obj) {
    _map[id] = obj;
    notifyListeners();
  }

  void remove(T id) {
    _map.remove(id);
    notifyListeners();
  }
}

import 'object_list_provider.dart';
import '../person.dart';

class PersonList extends ObjectListProvider {
  final Map<dynamic, Person> _people = {};
}

import './object_list_provider.dart';
import '../group.dart';
import '../person.dart';

class GroupList extends ObjectListProvider {
  final Map<dynamic, Group> _groups = {};

  void addPersonToGroup<T extends num>(Person person, T id) {
    super.add(id, person);
    notifyListeners();
  }

  void removePersonFromGroup<T extends num>(Person person, T id) {
    _groups[id]?.removePerson(id);
    notifyListeners();
  }
}

import './person.dart';
import './transaction.dart';

class Group {
  final int _id;
  String _name;
  List<Person> _people = [];
  List<Transaction> _transactions = [];
  int _totalSpending;

  Group({required int id, required String name, int totalSpending = 0})
      : _id = id,
        _name = name,
        _totalSpending = totalSpending;

  int get id {
    return _id;
  }

  String get name {
    return _name;
  }

  int get totalSpending {
    return _totalSpending;
  }

  set name(String newName) {
    _name = newName;
  }

  void addPerson(Person person) {
    _people.add(person);
  }

  void removePerson<T extends num>(T id) {
    _people = _people.where((Person person) => person.id != id).toList();
  }

  void addTransaction(Transaction transaction) {
    _transactions.add(transaction);
  }
}

class Person {
  final int _id;
  final String _name;
  int _balance;
  List<int> involvedGroups = [];

  Person({required int id, required String name, int balance = 0})
      : _id = id,
        _name = name,
        _balance = balance;

  int get id {
    return _id;
  }
}

For example, I will use this provider in some other dart file as

final groupList = Provider.of<GroupList>(context);
groupList.add(....)

CodePudding user response:

I refactored my code and came up with a solution that worked for me. Let me try to explain future reads as much as I can.

changed map from private to public. I am not sure it is the best way but it worked for this case. I was also able to work it with getter and setters but by doing that provider object did end up having two variables as _map and map.

import 'package:flutter/material.dart';

class ObjectListProvider<T extends num, K extends Object> with ChangeNotifier {
  Map<T, K> map = {};

  K? getSingleObjectWithId(id) {
    return map[id];
  }

  void add(T id, K obj) {
    map[id] = obj;
    notifyListeners();
  }

  void remove(T id) {
    map.remove(id);
    notifyListeners();
  }
}

Add generics after extending. This way I was able to access the map variable which previously I made publicly accessible. did the same thing for the PersonList as well.

import './object_list_provider.dart';
import '../group.dart';
import '../person.dart';

class GroupList extends ObjectListProvider<num, Group> {

  void addPersonToGroup<T extends num>(Person person, T id) {
    super.map[id]?.addPerson(person);
    notifyListeners();
  }

  void removePersonFromGroup<T extends num>(Person person, T id) {
    super.map[id]?.addPerson(person);
    notifyListeners();
  }
}

Other than these I did not changed anything related. Now I can call and use provider in some other file as

...

@override
  Widget build(BuildContext context) {
    final groupList = Provider.of<GroupList>(context);
    final groups = groupList.map;

    return ListView.builder(
      itemCount: groups.length,
      itemBuilder: (context, int index) {
        return ListTile(
          onTap: () => index,
          title: Text(groups[groups.keys.elementAt(index)]!.name),
          trailing: Text(
            groups[groups.keys.elementAt(index)]!.totalSpending.toString(),
          ),
        );
      },
    );
  }

...

CodePudding user response:

I'm working on something simmilar(not current version) at the moment. I would like to try and help if and where I can - though with the caveat that I'm still figuring out a lot of the basics myself.

Could you narrow-down or re-phrase the problem?

What I've done in the app I linked to above, as far as I think it might be relevant to you after a quick skim through your code, what I've done is:

  • To 'hold' the list and as much as possible of the functionality in the parent class.
  • In my case, each child class extends that parent - I'm calling it a 'listicle', and the type of object is specific to that childTypeListicle (for now).
  • The child classes hold specification of the types they list - in my case each it type shares an abstract parent Item class - as well as some config details for e.g. remote access and factory constructors. These' fields communicate up to the parent interfacing and its generic-ized functionality around the list through abstract method declarations enforced by the shared parent class. So that crteates a kind of the list as axel while it its reasonably item-type agnostic. Make sense?

Seems to work well so far, basically holds the logic this side of the plane-of-presentation implementation.

I also have tertiary connected interface elements like bottom-alert-bar connecting into fields of the parent 'listicle', and creating a kind of navigation ui that manipulates the list out onto the listview builder. Would like to also build in some partial local repository-ing but that doesn't seem a priority at the moment for this project.

I hope some of that helps somehow.

  • Related