- vừa được xem lúc

Reflectable Flutter - Listing widgets in your project

0 0 9

Người đăng: Vịnh Ngô

Theo Viblo Asia

Reflectable

Reference

https://marketsplash.com/tutorials/dart/dart-metadata/

https://itnext.io/understanding-reflection-and-annotations-in-dart-f1e28efdb064#:~:text=To reflect on types and,passed in as the argument

Metadata

https://dart.dev/language/metadata

https://api.flutter.dev/flutter/meta/meta-library.html

dart: Mirror - Status: Unstable

https://api.dart.dev/stable/3.1.3/dart-mirrors/dart-mirrors-library.html

Use Cases For Metadata

Metadata finds its application in various scenarios:

  • Code Documentation: By annotating code with metadata, developers can provide richer context, aiding in code understanding and documentation generation.
  • Tooling and Libraries: Tools and libraries can leverage metadata to automate tasks, provide warnings, or offer suggestions.
  • Code Generation: Metadata can be used to generate boilerplate code, reducing manual effort and potential errors.

Description

Listing all the widgets in a Flutter project is like a document that helps developers quickly identify existing widgets within the current project. This can aid in reusing widgets, reducing development time.

Dependencies:

in pubspec.yaml

dependencies: //https://pub.dev/packages/reflectable reflectable: ^4.0.5 dev_dependencies: //support generate code //https://pub.dev/packages/build_runner build_runner: ^2.4.6

Config:

Create annotation type:

import 'package:reflectable/reflectable.dart'; class SampleWidget extends Reflectable { const SampleWidget() : super(invokingCapability, typingCapability, reflectedTypeCapability);
} const sampleWidget = SampleWidget();

Create widget is marked by SampeWidget annotation

import 'package:flutter/material.dart';
import 'package:flutter_reflectable/sample_annotation.dart'; class GreenBoxWidget extends StatelessWidget { const GreenBoxWidget({Key? key, this.width, this.height}) : super(key: key); final double? width; final double? height;  Widget build(BuildContext context) { return Container( color: Colors.green, width: width, height: height, ); }
} 
class SampleGreenBoxWidget extends StatelessWidget { const SampleGreenBoxWidget({super.key});  Widget build(BuildContext context) { return const GreenBoxWidget( height: 100, width: 100, ); }
}

Config to generate

In main.dart

///*important
///need import 'package:flutter_reflectable/widgets/widget.dart';
import 'package:flutter_reflectable/widgets/widget.dart'; import 'main.reflectable.dart'; 

main.reflectable.dart: this file will be generated

In widgets/widget.dart

///*important
///need import this file to able generate code export 'red_box_widget.dart';
export 'green_box_widget.dart';

We need to import this file to generate can detect what annotation need to generate

Run script:

dart run build_runner build

Config show UI

void main() { //this [initializeReflectable] required to call reflectable initializeReflectable(); runApp(const MyApp());
}
class SampleListWidget extends StatelessWidget { const SampleListWidget({Key? key}) : super(key: key);  Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Widget by sample annotation')), body: Column( children: sampleWidget.annotatedClasses.map((e) => e.newInstance('', []) as Widget).toList(), ), ); }
}
//main value of this article
sampleWidget.annotatedClasses.map((e) => e.newInstance('', []) as Widget).toList(),

sampleWidget.annotatedClasses: get all Type were marked with @sampleWidget

e.newInstance('', []) : get an instance of each type by call default constructor (it have no param arguments)

The result

image.png

Apply with StoryBook

Introduce about story book and import it

https://pub.dev/packages/storybook_flutter

Define Story book name

const String defaultName = 'unknown'; mixin StoryBookName on Widget { String get name;
}

Need to define StoryBookName because in current time can not pass value to Annotation type

///This code not work for generate code
///This is current limit in Reflectable of Dart
class SampleWidget extends Reflectable { const SampleWidget(this.name) : super(invokingCapability, typingCapability, reflectedTypeCapability); final String name;
}

Add mixin for SampeWidget


class SampleGreenBoxWidget extends StatelessWidget with StoryBookName { const SampleGreenBoxWidget({super.key});  Widget build(BuildContext context) { return const GreenBoxWidget( height: 100, width: 100, ); }  String get name => 'box/green-box';
}

Widget without mixin

class DefaultNameBox extends StatelessWidget { const DefaultNameBox({Key? key, this.width, this.height}) : super(key: key); final double? width; final double? height;  Widget build(BuildContext context) { return Container( color: Colors.grey, width: width, height: height, child: const Text(defaultName), ); }
} 
class SampleDefaultNameBoxWidget extends StatelessWidget { const SampleDefaultNameBoxWidget({super.key});  Widget build(BuildContext context) { return const DefaultNameBox( height: 100, width: 100, ); }
}

** 💡 remember add export to widget.dart export 'default_name_box_widget.dart';**

Set up story book widget

class ReflectableStoryBookWidget extends StatelessWidget { const ReflectableStoryBookWidget({Key? key}) : super(key: key);  Widget build(BuildContext context) { return Storybook( plugins: initializePlugins( initialDeviceFrameData: ( isFrameVisible: true, device: Devices.ios.iPad, orientation: Orientation.portrait, ), ), stories: sampleWidget.annotatedClasses .where((classMirror) => !classMirror.isAbstract) .map((e) => e.newInstance('', [])) .whereType<Widget>() .map((e) => Story(name: e is StoryBookName ? e.name : defaultName, builder: (_) => e)) .toList(), ); }
}

💡 remember re run generate script

The result

Conclusion

Git: https://github.com/1712916/flutter-reflectable

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 281

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

0 0 207

- vừa được xem lúc

Dart Cheat Sheet - Full bộ "bỏ túi" các syntax trong ngôn ngữ Dart

Dart là một ngôn ngữ mới dùng cho cả Mobile và Web với Flutter Framework, thậm chí dùng cho Backend. Để giúp mọi người dễ dàng nắm bắt ngôn ngữ này hơn, 200lab Education đã tổng hợp thành bộ "bí tịch" dưới đây để tra cứu nhanh, tăng tốc phát triển phần mềm.

0 0 51

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 2: StatefulWidget vs StatelessWidget. Khi nào thì cần sử dụng cái nào?

Lời mở đầu. Ở bài trước, chúng ta đã dừng lại ở một kết thúc mở.

0 0 96

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 4: Lột trần InheritedWidget

Lời mở đầu. Trong đoạn kết của phần 2, chúng ta đã đối mặt với 1 bài toán: Làm thế nào để truyền data từ một widget cha nào đó xuống thẳng widget chắt mà không phải sử dụng constructor để truyền xuống

0 0 67

- vừa được xem lúc

Chinh phục RxDart Flutter trong 3 nốt nhạc. Nốt thứ nhất: Stream và giải thích các thuật ngữ

Lời mở đầu. Mình viết series này với mục đích chia sẻ kiến thức về RxDart trong Flutter.

0 0 74