using "mixin" to factor out code to different files - flutter

I am trying to factor out some code(inspired from this)
part "game.dart":
part 'taps.dart';
class MyGame extends FlameGame with HasTappables {}
Trying to factor out to this file "taps.dart":
part of 'game.dart';
mixin Taps on MyGame {
#override
void onTapDown(int pointerId, TapDownInfo info) {
super.onTapDown(pointerId, info);
}
Problem is that "onTapDown" is not called?
Update:
This will not work:
class MainClass with OneMixin {
void test(){
helloOne();
}
}
mixin OneMixin on MainClass {
void helloOne() {
test();
}
}

Something like this would work:
abstract class FlameGame {
int? a;
}
class MyGame extends FlameGame with Taps {
int? b;
}
mixin Taps on FlameGame {
void method() {
print(a); // Possible
print(b); // Not possible
print((this as MyGame).b); // possible but unsave
}
}

Related

Best way to shrink service class to smaller pieces

Currently making a large app with Flutter and I m stuck on the architecture of service class. There is a service class for the firestore CRUD operations.This class has many methods and I want split it into small pieces. I use an abstract class to protect methods.I find a way with mixins but don't know it's a good one or not.
https://gist.github.com/pMertDogan/fcd301d768f3980a898cec33a9acaa4f.
//Extend CRUDSERVICE rules aka abstract class => Test
mixin Update{
void updateSomething();
}
mixin Read{
void readSomething();
}
//BASE class for CRUDSERVICE
abstract class Test with Update,Read{
doSomeCreateOP(String x);
}
//
class CrudService extends Test with UpdateService , ReadService{
#override
doSomeCreateOP(String x) {
print('crated ' + x);
}
}
mixin UpdateService{
// #override
void updateSomething() {
print('updated');
}
}
mixin ReadService{
// #override
void readSomething() {
print('read');
}
}
void main() {
CrudService croudService = CrudService();
croudService.doSomeCreateOP(' dartSide');
croudService.updateSomething();
croudService.readSomething();
}
CreateService and UpdateService mixins are just sample.I am thinking like if I need update user information all methods are handed by UserServiceMix mixin if it's Friend then its hanled by FriendServiceMix so I can split them like a domain-based.Each mixin is responsible for specific operations.I can manage then on independent files and summary of them with the help of mixin.
Is it good way to go?
I believe it is a good way to go. It is a quite flexible approach. We use it for API versioning as well.
abstract class Service {
void method1();
void method2();
}
mixin Method1V1 {
void method1() {
print("method1");
}
}
mixin Method2V1 {
void method2() {
print("method2");
}
}
mixin Method2V2 {
void method2() {
print("method2 with changed logic");
}
}
class ServiceV1 extends Service with Method1V1, Method2V1 {
}
class ServiceV2 extends Service with Method1V1, Method2V2 {
}
void main() {
final version = 2;
final Service service = version == 1 ? ServiceV1() : ServiceV2();
service.method2();
}

Flutter generalized parameter?

I have a flutter app that uses a database what is generated by Moor.
Normally I would need 3 pages but since all 3 pages would look the same, the code would be the same. Only difference is the DAO they use.
So I have FirstDao, SecondDao, ThirdDao. All of them have the list() method and all of them return different type of objects (FirstType, SecondType, ThirdType) At the moment this is how I made it work but I am not sure is this a good way:
class RollingListChoice<T> extends StatefulWidget {
T dao;
RollingListChoice(this.dao);
#override
_RollingListChoiceState createState() =>
_RollingListChoiceState(dao);
}
class _RollingListChoiceState<T> extends State<RollingListChoice> {
T dao;
_RollingListChoiceState(this.dao);
#override
Widget build(BuildContext context) {
return Text(getDao().list());
}
getDao() {
if (dao.runtimeType == FirstDao) {
FirstDao mydao = dao as FirstDao;
return mydao;
} else if (dao.runtimeType == SecondDao) {
SecondDaomydao = dao as SecondDao;
return mydao;
} else if (dao.runtimeType == ThirdDao) {
ThirdDao mydao = dao as ThirdDao;
return mydao;
}
}
}
Any way to improve the code? Is there any best practice for this type of problem?
you can have an interface for DAO classes (for example IDAO) and replace RollingListChoice<T> with RollingListChoice<T extends IDAO> to restrict type T to specific classes. by that, you don't need to cast dao in getDao() method and you will be sure that dao has list() method.
abstract class IDAO {
String list();
}
class RollingListChoice<T extends IDAO> extends StatefulWidget {
T dao;
RollingListChoice(this.dao);
#override
_RollingListChoiceState createState() =>
_RollingListChoiceState(dao);
}
class _RollingListChoiceState<T extends IDAO> extends State<RollingListChoice> {
T dao;
_RollingListChoiceState(this.dao);
#override
Widget build(BuildContext context) => Text(dao.list());
}
if you do mentioned changes you don't need to getDao() method, but you can change getDao() method like this as well:
getDao() {
if (dao is FirstDao) {
FirstDao mydao = dao as FirstDao;
return mydao;
} else if (dao is SecondDao) {
SecondDaomydao = dao as SecondDao;
return mydao;
} else if (dao is ThirdDao) {
ThirdDao mydao = dao as ThirdDao;
return mydao;
}
}

How to get function body as string using build_runner and source_gen?

My goal is to make my unit tests easy to understand. Currently, they are hard to understand because they have so many nested functions.
I want to use build_runner to generate the code of the unit with all functions unwrapped.
So here is an example of my current test:
test.dart
import 'package:example_usage/src/unwrap.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
class Cat {
String sound() => "Meow";
int walk() => 4;
}
class Dog {
final Cat cat;
Dog(this.cat);
String sayHi() {
return this.cat.sound();
}
int jump() {
return this.cat.walk();
}
}
class MockCat extends Mock implements Cat {}
void main() {
MockCat cat;
Dog dog;
#UnWrap()
void setupCatSoundStub() {
when(cat.sound()).thenReturn("Woof");
}
#UnWrap()
void setupCatWalkstub() {
when(cat.walk()).thenReturn(2);
}
#UnWrap()
void expectCatCalled() {
verify(cat.sound());
}
#UnWrap()
void testDogWoof() {
setupCatSoundStub();
dog = Dog(cat);
final sound = dog.sayHi();
expect(sound, "Woof");
expectCatCalled();
}
void expectCatWalked() {
verify(cat.walk());
}
group('Dog Cat Play', () {
setUp(() {
cat = MockCat();
});
test('Dog woof', () {
testDogWoof();
});
test('Dog woof then jump', () {
testDogWoof();
setupCatWalkstub();
final steps = dog.jump();
expect(steps, 2);
expectCatWalked();
});
});
}
I want to generate a code like this
_$test.dart
void _$main() {
MockCat cat;
Dog dog;
void expectCatWalked() {
verify(cat.walk());
}
group('Dog Cat Play', () {
setUp(() {
cat = MockCat();
});
test('Dog woof', () {
// testDogWoof();
// setupCatSoundStub();
when(cat.sound()).thenReturn("Woof");
dog = Dog(cat);
final sound = dog.sayHi();
expect(sound, "Woof");
// expectCatCalled();
verify(cat.sound());
});
test('Dog woof then jump', () {
// testDogWoof();
// setupCatSoundStub();
when(cat.sound()).thenReturn("Woof");
dog = Dog(cat);
final sound = dog.sayHi();
expect(sound, "Woof");
// expectCatCalled();
verify(cat.sound());
// setupCatWalkstub();
when(cat.walk()).thenReturn(2);
final steps = dog.jump();
expect(steps, 2);
expectCatWalked();
});
});
}
I found some tutorial online but I could find documentations about getting the function body into string ( some like JavaScript's Function.prototype.toString() method ) I am new to code generation so I tried to print all fields but I can't find anything like that.
import 'dart:async';
import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
class InfoGenerator extends Generator {
#override
FutureOr<String> generate(LibraryReader library, BuildStep buildStep) {
var buffer = StringBuffer();
// library.allElements.forEach((element) {
// buffer.writeln(
// '// ${element.displayName} - ${element.source.fullName} - ${element.declaration}');
// });
library.allElements.whereType<TopLevelVariableElement>().forEach((element) {
buffer.writeln('/*');
buffer.writeln(element.toString());
buffer.writeln('*/');
buffer.writeln(
'// ${element.name} - ${element.kind.displayName} - ${element.declaration}');
});
return buffer.toString();
}
}
I am also new to annotations so I just made this up
/// What to do here ?
class UnWrap {
const UnWrap();
}
Is what I am trying to do even possible ?

How to override a Dart method on instantiation? [duplicate]

Is there way to overriding method in Dart like JAVA, for example:
public class A {
public void handleLoad() {
}
}
And when overriding:
A a = new A() {
#Override
public void handleLoad() {
// do some code
}
};
No, Dart does not have anonymous classes. You have to create a class that extends A and instantiate it.
No but it much less useful in Dart because you can just reassign function:
typedef void PrintMsg(msg);
class Printer {
PrintMsg foo = (m) => print(m);
}
main() {
Printer p = new Printer()
..foo('Hello') // Hello
..foo = ((String msg) => print(msg.toUpperCase()))
..foo('Hello'); //HELLO
}
However you will need some extra boilerplate to access instance.
Use type Function:
class A {
final Function h
A(this.h);
void handleLoad(String loadResult) { h(loadResult); }
}
Or
class A {
final Function handleLoad;
A(this.handleLoad);
}
A a = new A((String loadResult){
//do smth.
});

Dart & flutter : How can I pass an implementation of an abstract class to the constructor of another class? [duplicate]

Lets say that I have an abstract class
abstract class OnClickHandler {
void doA();
void doB();
}
I have a class
class MyClass {
OnClickHandler onClickHandler;
MyClass({
this.onClickHandler
})
void someFunction() {
onClickHandler.doA();
}
}
And I have a class
class Main implements onClickHandler {
// This throws me an error
MyClass _myClass = MyClass(onClickHandler = this); // <- Invalid reference to 'this' expression
#override
void doA() {}
#override
void doB() {}
}
How can I say that use the same implementations that the Main class has? or is there an easier/better way to do this?
Your problem is that this does not yet exists since the object are still being created. The construction of Dart objects is done in two phases which can be difficult to understand.
If you change you program to the following it will work:
abstract class OnClickHandler {
void doA();
void doB();
}
class MyClass {
OnClickHandler onClickHandler;
MyClass({this.onClickHandler});
void someFunction() {
onClickHandler.doA();
}
}
class Main implements OnClickHandler {
MyClass _myClass;
Main() {
_myClass = MyClass(onClickHandler: this);
}
#override
void doA() {}
#override
void doB() {}
}
The reason is that code running inside { } in the constructor are executed after the object itself has been created but before the object has been returned from the constructor.