Where is the definition of `map.clear()`? - flutter

I'm checking the implementation of Map. (map.dart in dart:collection)
I find void clear(); in abstract class Map<K, V>. clear() doesn't have any implementation and class Map doesn't extend/implement any other classes. But I can still call clear().
example
Map<int, int> m = <int, int>{1: 1, 2: 2};
m.clear();
Where can I find the implementation of clear()?

My answer is based on the assumption that you want the implementation used when Dart is running natively and not on the web.
The default Map in Dart is a LinkedHashMap. There are several layers before getting the implementation of clear() but I expect this is the one you are looking for:
void clear() {
if (!isEmpty) {
_index = _uninitializedIndex;
_hashMask = _HashBase._UNINITIALIZED_HASH_MASK;
_data = _uninitializedData;
_usedData = 0;
_deletedKeys = 0;
}
}
https://github.com/dart-lang/sdk/blob/2.15.1/sdk/lib/_internal/vm/lib/compact_hash.dart#L333-L341

The {} notation creates a LinkedHashMap and that's where you'll find the implementation. See:
import 'dart:collection';
void main () {
Map<int, int> m = <int, int>{1: 1, 2: 2};
if(m is LinkedHashMap) {
print("It's a LinkedHashMap!");
}
}
Output:
It's a LinkedHashMap!

Related

what is Get.create() in the Getx package and what it does

reading the Getx package documentation, I faced this method:
Get.create<ShoppingController>(() => ShoppingController());
and it says:
Get.create(()=>Controller()) will generate a new Controller each time you call Get.find(),
but, I don't seem to understand what this means and how it differs from the Get.put() and Get.lazyPut().
I found the answer for that question.
The big difference between
Get.create<ShoppingController>(() => ShoppingController());
And :
Get.put(ShoppingController());
Both of them are used in injecting dependencies in the a Flutter app, But Get.put<T>(T()) injects it just one time and whenever we call Get.find<T>() it looks up for that exact dependency and return it, so we can rememeber this:
Get.put<T>(()) inject a dependency and whatever time we call Get.find<T>() across the entire app, the same T is returned.
In the other side, Get.create<V>(() => V) also inject a dependency in a Flutter app, But every time we call Get.find<V>(), it doesn't return the same V, it creates a new instance of V, then return it, so we can rememeber this:
Get.create<V>(() => V) don't return the same instance, it creates a new one every time Get.find<V>() is called.
Get.put(T()) :
class ControllerOne extends GetxController {
int number = 10;
increment() {
number += 10;
}
}
final controllerOne = Get.put<ControllerOne>(ControllerOne());
final controllerOneFinder = Get.find<controllerOne>();
controllerOneFinder.increment();
final controllerOneSecondFinder = Get.find<controllerOne>();
print(controllerOneFinder.number); // 20
print(controllerOneSecondFinder.number); // 20
it stay the same.
Get.create(() =>T) :
class ControllerTwo extends GetxController {
int secondNumber = 10;
increment() {
secondNumber += 10;
}
}
final controllerTwo = Get.create<ControllerTwo>(() => (ControllerTwo());
final controllerTwoFinder = Get.find<ControllerTwo>();
controllerTwoFinder.increment();
final controllerTwoSecondFinder = Get.find<ControllerTwo>();
print(controllerTwoFinder.number); // 20
print(controllerTwoSecondFinder.number); // 10
Each one is different than the other. (controllerTwoSecondFinder == controllerTwoFinder) is false.

How can I test a method and to mock another method that are in the same class in Flutter

Description:
I have already tested methodA() and methodB() so I can be sure that they are covered.
What are the ways to test methodToBeTested() by mocking methodA() and methodB() that are in the same file? The parameters are passed through the methodToBeTested() to the methodA() and methodB() to properly test these methods using injection.
Note: They are cannot be extracted to a different class since it is a related logic of the calculation service and these methods are already atomically is separated.
Code:
class ClassForTesting {
int methodToBeTested(String a, String b) {
// Calculation in this method also is a bit more difficult
return methodA() + methodB();
}
int methodA(String a) {
int value = 1;
// Here is calculation logic that has been tested
return value;
}
int methodB(String b) {
int value = 2;
// Here is calculation logic that has been tested
return value;
}
}
What has been done:
I have tried several approaches from Mockito, but it doesn't allow to do such a trick:
#GenerateMocks - is creating a mock and requires me to stub each method using when(), even methodToBeTested().
By extending Fake using the next construction:
class Mock extends Fake implements PasswordValidatorService {}
But in this way, I'm only inheriting the PasswordValidatorService's behavior instead of instead implementation and each non-overridden method throws UnimplementedError. Thus, I'm not able to override methodToBeTested() and call its super implementation.
I found that Mockito for Java has #Spy construction that would be perfect in this case but unfortunately it is not available for Dart and Flutter.
The only way I currently came is to create my own Mock:
class MockClassForTesting extends ClassForTesting {
#override
int methodA() {
return 2;
}
#override
int methodB() {
return 5;
}
}
But this implementation doesn't allow me to use Mockito's flexibility of when() construction since I must have different methodA() and methodB() returns.
This fact forces me to have additional variables in my MockClassForTesting to achieve when() construction functionality.
The questions:
What would be the best way to achieve my purposes?
Can be the same mocking approach to be used during the Widget testing?
One approach would be to use a hybrid approach where you create your own derived class but where some of its overrides delegate to a Mock implementation. For example:
class ClassForTesting {
int methodToBeTested(String a, String b) {
// Calculation in this method also is a bit more difficult
return methodA(a) + methodB(b);
}
int methodA(String a) {
int value = 1;
// Here is calculation logic that has been tested
return value;
}
int methodB(String b) {
int value = 2;
// Here is calculation logic that has been tested
return value;
}
}
class PartialMockClassForTesting extends ClassForTesting {
final mock = MockClassForTesting();
#override
int methodA(String a) => mock.methodA(a);
#override
int methodB(String b) => mock.methodB(b);
}
#GenerateMocks([ClassForTesting])
void main() {
test('Test partial mock', () {
var partialMock = PartialMockClassForTesting();
when(partialMock.methodA('hello')).thenReturn(42);
when(partialMock.methodA('goodbye')).thenReturn(-42);
when(partialMock.methodB('world')).thenReturn(10);
expect(partialMock.methodToBeTested('hello', 'world'), 52);
expect(partialMock.methodToBeTested('goodbye', 'world'), -32);
});
}
If you want to conditionally mock certain methods, you could have your overrides check boolean flags to conditionally call either the mock or the real implementation. For example:
class PartialMockClassForTesting extends ClassForTesting {
final mock = MockClassForTesting();
final shouldMock = <Function, bool>{};
#override
int methodA(String a) =>
shouldMock[methodA] ?? false ? mock.methodA(a) : super.methodA(a);
#override
int methodB(String b) =>
shouldMock[methodB] ?? false ? mock.methodB(b) : super.methodB(b);
}
#GenerateMocks([ClassForTesting])
void main() {
test('Test partial mock', () {
var partialMock = PartialMockClassForTesting();
partialMock.shouldMock[partialMock.methodA] = true;
partialMock.shouldMock[partialMock.methodB] = true;
...

Dart Analysis Detects and Unused Field...what am I missing?

As you can see from my code sample, I'm using this variable. I also reference multiple times later in the class.
Flutter Warning - info: The value of the field '_loadTimer' isn't used. (unused_field at [app] lib/models/knowledge_level/pb_cycle_permissions_collection.dart:12)
ng is: info: The value of the field '_loadTimer' isn't used. (unused_field at [app] lib/models/knowledge_level/pb_cycle_permissions_collection.dart:12)
import 'dart:async';
import 'dart:collection';
import 'package:app/data/graphql/queries.dart';
import 'package:app/helpers/shared_logger.dart';
import 'package:flutter/cupertino.dart';
import '../command_permission.dart';
class PBCyclePermissionsCollection
with ListMixin<CommandPermission>, ChangeNotifier {
Timer? _loadTimer;
///
/// CONSTRUCTION AND INITIALIZATION
///
static final PBCyclePermissionsCollection _instance =
PBCyclePermissionsCollection._internal();
factory PBCyclePermissionsCollection() {
return _instance;
}
/// ACCESS SINGLETON VIA myPBCyclePermInstance = PBCyclePermissionsCollection()
PBCyclePermissionsCollection._internal() {
_loadTimer = Timer(_waitFirstLoad, _attemptLoad);
}
///
/// PRIVATE VARIABLES AND METHODS
///
static final Duration _waitFirstLoad = Duration(milliseconds: 500);
static final Duration _waitRetryLoad = Duration(seconds: 2);
static final int _maxAttempts = 4;
int _loadAttempts = 0;
bool _isReady = false;
bool _hasFailed = false;
/// Storage of CommandPermissions List once loaded
final List<CommandPermission> _list = [];
void _attemptLoad() async {
_loadAttempts++;
SharedLogger.I().d('_attemptLoad() current load attempt: ${_loadAttempts}');
try {
final results = await Queries.getCommandPermissions();
var data = results.data!['commandPermissions'];
var permissions = <CommandPermission>[];
for (var item in data) {
permissions.add(CommandPermission.fromJson(item));
}
/// Populated class with loaded objects.
_list.clear();
_list.addAll(permissions);
_isReady = true;
notifyListeners();
} catch (e) {
SharedLogger.I().e('Error loading PBCycle Permissions - ${e}');
_newAttempt();
}
}
void _newAttempt() {
SharedLogger.I().d(
'_newTry() _loadAttempts: ${_loadAttempts} _maxAttempts:${_maxAttempts} '
'creating new loadTimer for another try? : ${!(_loadAttempts >= _maxAttempts)}');
if (_loadAttempts >= _maxAttempts) {
_hasFailed = true;
notifyListeners();
// TODO: do we invalidate any existing data that may have been loaded before? Like if this load cycle is a refresh?
// If so, we should reset _isReady and _list;
return;
}
_loadTimer = Timer(_waitRetryLoad, _attemptLoad);
}
///
/// PUBLIC METHODS
///
bool get isLoaded {
return _isReady;
}
bool get hasFailed {
return _hasFailed;
}
#override
set length(int newLength) {
throw ('length cannot be changed externally');
}
#override
int get length {
return _list.length;
}
#override
CommandPermission operator [](int index) {
return _list[index];
}
#override
void operator []=(int index, CommandPermission value) {
throw ('Cannot modify list from outside');
}
}
Image of IDE with Code Sample and associated Dart Analysis Hints
You aren't actually using it, you're just setting the value multiple times
The answer from Andrew is correct, but a bit unclear since unsure what 'it' refers to. Here's another way to explain what the warning message means:
Notice that the message says you are not using the value. You are using the variable, but not its value. You are assigning the value. To read the value would be using it.
That said, the question is answered, but I think the question is somewhat vague by asking "what am i missing". What do you (OP) want to achieve? I assume it's to not see that warning anymore. And that is what brings me to this post. I have similar issue. I too have a class variable for a Timer and I get this same warning message. One does not need to read the value in order to use a timer but the analyzer doesn't know that. While writing this response I have discovered that you can a suppress warning. How about this:
// ignore: unused_field
Timer? _loadTimer;

Dart can you overload the assignment operator?

I have the following class:
class EventableNumber{
num _val;
num get val => _val;
void set val(num v){
num oldValue = _val;
_val = v;
_controller.add(new NumberChangedEvent(oldValue, v));
}
StreamController<NumberChangedEvent> _controller = new StreamController<NumberChangedEvent>();
Stream<NumberChangedEvent> _stream;
Stream<NumberChangedEvent> get onChange => (_stream != null) ? _stream : _stream = _controller.stream.asBroadcastStream();
EventableNumber([num this._val = 0]);
}
Is it possible to overload the = assignment operator? rather than using the val getter and setter to enforce the event to fire when the value changes it would be nice if it could just be done when the user writes myEventableNum = 34 and then myEventableNum first its onChange event, rather than myEventableNum.val = 34.
Dart doesn't allow this.
However, have you considered a function style call?
Basically, if you define a function called 'call' in EventableNumber class, then you can call the instance as a function:
myEventableNum(34)
If you decided to go this way, it is recommended to implement the Function interface:
class EventableNumber implements Function {
...
void call(val) {...}
...
}
Hope this helps :)

Extending base List class with extra functionality in Dart language

This question is about Dart language.
I want to have a class which is just a List but with some extra functionality.
For example I have a class named Model:
class Model{
String name;
int type;
Model(this.name, this.type);
}
I know that Model's type could take only four values: from 0 to 3.
And I want to have a method, which can give me a List of Models of specified type, e.g. List<Model> modelCollection.getByType(int type);.
I plan to to have four 'hidden' Lists of the Models (grouped by type) in that class.
Thus I need to override addition and removal of List elements to make that hidden lists being up to date.
How can I realize this as easy as possible?
P.S. I know this is quite simple, but I'm poorly familiar with Object inheritance and can't find proper examples.
P.P.S. I've also checked this but don't know is it outdated or not and didn't catch the idea.
To make a class implement List there are several ways :
Extending ListBase and implementing length, operator[], operator[]= and length= :
import 'dart:collection';
class MyCustomList<E> extends ListBase<E> {
final List<E> l = [];
MyCustomList();
void set length(int newLength) { l.length = newLength; }
int get length => l.length;
E operator [](int index) => l[index];
void operator []=(int index, E value) { l[index] = value; }
// your custom methods
}
Mixin ListMixin and implementing length, operator[], operator[]= and length= :
import 'dart:collection';
class MyCustomList<E> extends Base with ListMixin<E> {
final List<E> l = [];
MyCustomList();
void set length(int newLength) { l.length = newLength; }
int get length => l.length;
E operator [](int index) => l[index];
void operator []=(int index, E value) { l[index] = value; }
// your custom methods
}
Delegating to an other List with DelegatingList from the quiver package:
import 'package:quiver/collection.dart';
class MyCustomList<E> extends DelegatingList<E> {
final List<E> _l = [];
List<E> get delegate => _l;
// your custom methods
}
Depending on your code each of those options have their advantages. If you wrap/delegate an existing list you should use the last option. Otherwise use one of the two first options depending on your type hierarchy (mixin allowing to extend an other Object).
A basic approach is to extend an Object with IterableMixin. It also seems that you don't even need to override the "length" getter or let's say all methods that the IterableMixin already provides.
import 'dart:collection';
class Model {
String name;
int type;
Model(this.name, this.type) {
}
}
class ModelCollection extends Object with IterableMixin {
List<Model> _models;
Iterator get iterator => _models.iterator;
ModelCollection() {
this._models = new List<Model>();
}
//get one or the first type
Model elementByType(int type) {
for (Model model in _models) {
if (model.type == type) {
return model;
}
}
}
//get all of the same type
List<Model> elementsByType(int type) {
List<Model> newModel = new List<Model>();
for (Model model in _models) {
if (model.type == type) {
newModel.add(model);
}
}
return newModel;
}
add(Model model) {
this._models.add(model);
}
}
Excuse my strong static typing.
You might be interested in quiver.dart's Multimap. It behaves like a Map that allows multiple values per key.
Here's the code on github: https://github.com/google/quiver-dart/blob/master/lib/src/collection/multimap.dart#L20
It's on pub simply as quiver. We'll be hosting the dartdocs somewhere soon.