[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-9190":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":16,"starSnapshotCount":16,"syncStatus":26,"lastSyncTime":27,"discoverSource":28},9190,"awesomefluttertips","erluxman\u002Fawesomefluttertips","erluxman","❤️ Awesome Flutter Tips and Tricks  ❤️","",null,"Dart",2944,249,179,6,0,1,56.29,false,"master",true,[],"2026-06-12 04:00:43","# ❤️Awesome Flutter ❤️ tips and tricks ❤️\n[![Hits](https:\u002F\u002Fhits.seeyoufarm.com\u002Fapi\u002Fcount\u002Fincr\u002Fbadge.svg?url=https%3A%2F%2Fgithub.com%2Ferluxman%2Fawesomefluttertips&count_bg=%2379C83D&title_bg=%23555555&icon=prometheus.svg&icon_color=%23E7E7E7&title=hits&edge_flat=true)](https:\u002F\u002Fhits.seeyoufarm.com)\u003Ca href=\"https:\u002F\u002Fgithub.com\u002FSolido\u002Fawesome-flutter\">\n   \u003Cimg alt=\"Awesome Flutter\" src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAwesome-Flutter-blue.svg?longCache=true&style=flat-square\" \u002F>\n\u003C\u002Fa>\n\n## Tip 1 : `stless` & `stful`\n\nWe can type `stless` and `stful` and we get Autocomplete Suggestion to generate Stateless Flutter Widget or Stateful Flutter Widget Respectively.\n\n![statful](assets\u002F01stlesstful.gif)\n\n## Tip 2 : `If Null` Operator (`??`)\n\n`??` checks If something is `null`. If it's not null it returns its own value but if it's `null` it returns the value after `??`\n\n`return abc??10; \u002F\u002Freturns 10 if abc is null else returns its own value,`\n\nIt also has shorthand assignment when it's null.\n\n`abc??=5 \u002F\u002Fassigns 5 to abc if it's null`\n\n```dart\ntestOldMethod() {\n  print(\"NullChecking in old way\");\n  var abc;\n  \n  if (abc == null) {\n    print(\"It's null\");\n  } else {\n    print(abc);\n  }\n\n  if (abc == null) {\n    abc = 5;\n  }\n}\n\ntestIfNullOperator() {\n  print(\"NullChecking with if Null Operator\");\n  var abc;\n\n  print(abc ?? \"It's null\");\n  abc ??= 5;\n  print(abc ?? \"It's null\");\n}\n```\nOutput:\n```\nNullChecking in old way\nIt's null\n5\n--------------------\nNullChecking with if Null Operator\nIt's null\n5\n```\n\n## Tip 3 : Inner Function\n\nWe can define a function inside another function.\n\nThis is to encapsulate the inner function from everything else outside the outer function.\n\n```dart\nmain() {\n  String getName() {\n\n    String getFirstName() { return \"Laxman\"; }\n\n    String getLastName() { return \"Bhattarai\"; }\n\n    return getFirstName() + \" \" + getLastName();\n  }\n\n  print(getName());\n}\n```\nOutput\n```\nLaxman Bhattarai\n```\n\n\n## Tip 4 : ..Cascade..Chaining..Fluent API\n\nWe can chain method\u002Fmember calls without returning `this` from **method(), getter() and setter()** using cascade operator (..)\n\ntry in [Dartpad](https:\u002F\u002Fdartpad.dartlang.org\u002F290e17306b745ed83b9242653ca55041)\n\nBefore:\n```dart\nclass User {\n  String name;\n  int age;\n\n  User({this.name = \"Foo\", this.age = 0});\n\n  User withName(String name) {\n    this.name = name;\n    return this;\n  }\n\n  User withAge(int age) {\n    this.age = age;\n    return this;\n  }\n\n  void printId() => print(\"$name is $age years old.\");\n}\n\nmain() {\n  User()\n  .withAge(27)\n  .withName(\"Laxman\")\n  .printId();\n}\n```\n\nCan be replaced with\n```dart\nclass User {\n  String name;\n  int age;\n\n  void printId() => print(\"$name is $age years old.\");\n}\n\nmain() {\n  User()\n  ..age = 27\n  ..name = \"Laxman\"\n  ..printId();\n}\n```\n\n## Tip 5 : Dart `data class`\n\nDart does not support data class by default, but with plugins, we can simply generate data class (`copyWith()`,`fromMap()`, `toMap()`, `Named Constructor`, `toString()`,`hashCode()` & `equals()` methods implemented by the tool).\n\n### `🚨❗️Caution❗️🚨` : **Your cursor should be inside the class that you want to generate data class.**\n\n![dataclass](assets\u002F05dataclass.gif)\n\nDownload Plugins :\n\n[For Android Studio](https:\u002F\u002Fplugins.jetbrains.com\u002Fplugin\u002F12429-dart-data-class)\n\n[For VsCode](https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=BendixMa.dart-data-class-generator)\n\n## Tip 6 : RichText Widget\n\nIf you want to have a single text with different style within it? Do not bother or try to hack with with `Text()` and use `RichText()` with `TextSpan()`\n\n[Try on dartpad](https:\u002F\u002Fdartpad.dartlang.org\u002Ff87dddb2f48f1d1ef0f25903af1ded58)\n\n[See Youtube Demo](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=rykDVh-QFfw)\n\n![richtext](assets\u002F06richtext.png)\n\n## Tip 7 : Spacer Widget\n\nUsing Container with certain height\u002Fwidth to create responsive space between Widgets? That may look good on one screen but will not look the same in different screen size.\n\nSpacer Widget comes for the rescue. Instead of `Container(width: \u002F height: )`, use `Spacer(flex: )`.\n\nHow on this earth did I not know about this widget earlier? This is going to save many lives 😂\n\n[Try on dartpad](https:\u002F\u002Fdartpad.dev\u002Ff0d077124527a8078cdb2eede1e9bf73)\n\n[See Youtube Demo](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=7FJgd7QN1zI)\n\n![spacer](assets\u002F07spacer.gif)\n\n## Tip 8 : ListView.separated()\n\nIf you have you been adding `Container()` with `maxwidth` at the bottom of `ListItem` to put divider line like me, you have been doing it wrong all the time.\n\nFlutter has `ListView.separated` just for that purpose. We have to also provide `separatorBuilder` in addition to what we already passed while using `ListView.builder`\n\n**Bonus 🍾🎁🎊🎉 : You do not have to check if the item is last in order not to draw divider after the last item.**\n\n[try in dartpad](https:\u002F\u002Fdartpad.dartlang.org\u002F31ec967b140ac6a5795c38ea4bdfd9a2)\n\n```dart\nListView.separated(\n  itemCount: 25,\n  separatorBuilder: (BuildContext context, int index) => Divider(\n    thickness: 1,\n  ),\n  itemBuilder: (BuildContext context, int index) {\n    return ListTile(\n      title: Text(\n        'Index Number $index',\n      ),\n    );\n  },\n);\n```\n\n## Tip 9 : Passing Function as parameter\n\nWe can simply pass a `function` as `parameter` like we pass a variable. When we want to call the passed function from calling function, we just call it with `()` at the end along with parameters if it accepts any.\n\n[try in dartpad](https:\u002F\u002Fdartpad.dev\u002Ffa46336f5c1b3287c6420d3b3a277178)\n\n```dart\nvoid main() {\n  f2(f1, 3);\n  f2(f1, 4);\n  f2(f1, 7);\n}\n\nf1(int venOrOdd) {\n  print(\"$evenOrOdd is ${evenOrOdd % 2 == 0 ? \"Even\" : \"Odd\"}\");\n}\n\nf2(Function(int) evenOrOddFunction, int argumentToPass) {\n  evenOrOddFunction(argumentToPass);\n}\n```\nOutPut\n```dart\n3 is Odd\n4 is Even\n7 is Odd\n```\n\n---\n\n## Tip 10 : Relative Import : the right way to import `.dart` files we have in our lib package\n\nEver wondered what is the right way to import a file in your own package?\n\nPrefer relative imports to absolute imports.\n\nWhy?\n\n- It's shorter and cleaner.\n- We can easily differentiate our files and third-party ones.\n- It makes sense, doesn't it?\n\n```\nmy_package\n└─ lib\n   ├─ src\n   │  └─ utils.dart\n   └─ api.dart\n```\nIf `api.dart` wants to import `utils.dart`, it should do so using:\n```dart\nimport 'src\u002Futils.dart';\n```\n\nAnd not:\n```dart\nimport 'package:my_package\u002Fsrc\u002Futils.dart';\n```\n\n## Tip 11 : Reusing Text Style\n\nTired of defining `textStyle` everytime you want to customize `Text`? **Even worse** if you have multiple theme (**dark, light, full black theme etc**).\n\njust use\n\n`Theme.of(context).textTheme.title`\n\nwhere there are other styles like `title` inside `textTheme`.\n\n[try in dartpad with theme example](https:\u002F\u002Fdartpad.dartlang.org\u002F5270714ce97853fc36db1b17c255c999)\n\n```dart\nText(\n  \"Title\",\n  style: Theme.of(context).textTheme.title,\n)\n```\n\n## Tip 12 : Use Literal to initialize growable collections\n\nIf we are to initialize growable collection, use literal initialization rather than with constructors.\n\n```dart\n\u002F\u002F Good\nvar points = [];\nvar addresses = {};\n\n\u002F\u002F Bad\nvar points = List();\nvar addresses = Map();\n\n\u002F\u002F With type argument\n\n\u002F\u002F Good\nvar points = \u003CPoint>[];\nvar addresses = \u003CString, Address>{};\n\n\u002F\u002F Bad\nvar points = List\u003CPoint>();\nvar addresses = Map\u003CString, Address>();\n```\n\n## Tip 13 : Fat arrow functions\n\nWe can use fat arrow `=>` members (`function, getter,setter`) in dart.\n\nI would not use `=>` if the declaration is not **ONE LINER**. But few lines are OK.\n\n[try on dartpad](https:\u002F\u002Fdartpad.dev\u002F76922028eccb4535f0cdddc8e4b17aa1)\n\n```dart\nvoid main() {\n  User()\n    ..firstName = \"Laxman\"\n    ..lastName = \" Bhattarai\"\n    ..age = 18\n    ..printUser();\n}\n\nclass User {\n  String firstName;\n  String lastName;\n  DateTime birthday;\n\n  String get fullName => firstName + lastName;\n\n  set age(int age) =>  birthday = DateTime.now().subtract(Duration(days: age * 365));\n\n  int get age => DateTime.now().year - birthday.year;\n\n  bool get isAdult => age >= 18;\n\n  printUser() => print(fullName + \" is a ${isAdult ? \"Adult\" : \"Child\"}\");\n}\n```\n\n## Tip 14 : FractionallySizedBox\n\nEver wanted the widget to have height and width exactly in the same proportion to it's screen's height and width?\n\nFractionallySizedBox is build exactly for that use case. Just give it the fraction you need for your height and width and it will handle everything else. The fraction value will range between 0.0 to 1.0\n\n```dart\nFractionallySizedBox(\n  widthFactor: 0.5,\n  heightFactor: 0.5,\n  child: Container(color: Colors.green),\n)\n```\n[try on codepen](https:\u002F\u002Fcodepen.io\u002Ferluxman\u002Fpen\u002FrNOLOzG)\n\n![fractionally](assets\u002F14fractionallysizedbox.gif)\n\n## Tip 15 : Flexible vs Expanded\n\nExpanded() is nothing more than Flexible() with\n\n```dart\nFlexible (fit: FlexFit.tight) = Expanded()\n```\n\nbut, Flexible uses `fit :FlexFit.loose` by default.\n\n**FlexFit.tight** = Wants to fit tight into parent taking as much space as possible.\n\n**FlexFit.loose** = Wants to fit loose into parent taking as little space as possible for itself.\n\n**flex** = The factor of space taken from parent. Mostly not fully used if `flex: FlexFit.loose` used i.e. `Flexible`.\n\n![flex](assets\u002F15flexibleexpanded.png)\n\nIf you fully read the following image, you will fully understand the difference between `Flexible` and `Expanded`\n\n```dart\nclass Flexible extends... {\n  \u002F\u002F\u002F The flex factor to use for this child\n  \u002F\u002F\u002F\n  \u002F\u002F\u002F If null or zero, the child is inflexible and determines its own size. If\n  \u002F\u002F\u002F non-zero, the amount of space the child's can occupy in the main axis is\n  \u002F\u002F\u002F determined by dividing the free space (after placing the inflexible\n  \u002F\u002F\u002F children) according to the flex factors of the flexible children.\n  final int flex;\n\n  \u002F\u002F\u002F How a flexible child is inscribed into the available space.\n  \u002F\u002F\u002F\n  \u002F\u002F\u002F If [flex] is non-zero, the [fit] determines whether the child fills the\n  \u002F\u002F\u002F space the parent makes available during layout. If the fit is\n  \u002F\u002F\u002F [FlexFit.tight], the child is required to fill the available space. If the\n  \u002F\u002F\u002F fit is [FlexFit.loose], the child can be at most as large as the available\n  \u002F\u002F\u002F space (but is allowed to be smaller).\n  final FlexFit fit;\n\n  ........\n}\n\nclass Expanded extends Flexible {\n  \u002F\u002F\u002F Creates a widget that expands a child of a [Row], [Column], or [Flex]\n  \u002F\u002F\u002F so that the child fills the available space along the flex widget's\n  \u002F\u002F\u002F main axis.\n  const Expanded({\n    Key key,\n    int flex = 1,\n    @required Widget child,\n  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);\n}\n```\n\n[try in codepen](https:\u002F\u002Fcodepen.io\u002Ferluxman\u002Fpen\u002FJjYKZGG)\n\n## Tip 16 : Bulk declaration\n\nIf you have been declaring each member separately all the time, you can declare members of same types at once.\n\nI wouldn't declare `age` and `shoeSize` at once because they are not related.\n\nWith great power comes great responsibility, Use this wisely.\n\n```dart\nclass Footballer {\n\n  String firstName = \"Lionel\";\n  String middleName = \"Andrés\";\n  String lastName = \"Messi\";\n\n  double weightKG;\n  double heightCM;\n\n  int goals;\n  int assists;\n  int tackles;\n  int takeons;\n  int saves;\n  int shots;\n}\n\n\u002F\u002F The class above can be replaced with:\nclass Footballer {\n\n  String firstName = \"Lionel\", middleName = \"Andrés\", lastName = \"Messi\";\n\n  double weightKG, heightCM;\n\n  int goals, assists, tackles, takeons, saves, shots;\n}\n```\n\n## Tip 17 : SliverAppBar \u002F Collapsable AppBar \u002F ParallaxHeader\n\nRemember CollapsableAppBar (android) \u002F ParallaxHeader (ios)? We have SliverAppBar in Flutter to do exactly that.\n\nTo use it, you will have to have a CustomScrollView as parent.\n\nthen you add two slivers of it.\n\n1. SliverAppBar\n2. SliverFillRemaining\n\nYou can play with values of snap, floating, pinned etc to get desired effect\n\n[try on dartpad](https:\u002F\u002Fdartpad.dartlang.org\u002F6874032a7a1ea129640b8f617f7ffed3)\n\n[see various types of SliverAppBars here](https:\u002F\u002Fapi.flutter.dev\u002Fflutter\u002Fmaterial\u002FSliverAppBar-class.html#snippet-container)\n\n![sliverappbar](assets\u002F17sliverappbars.gif)\n\n## Tip 18 : What the Key\n\n![keys](assets\u002F18keys.gif)\n\nEver wondered why we need GlobalKey(children : GlobalObjectKey, LabeledGlobalKey), LocalKey(children: ObjectKey, ValueKey & UniqueKey) right?\n\nThey are used to access or restore state In a statefulWidget (Mostly we don't need them at all if our widget tree is all Stateless Widgets).\n\n### Purpose (Key to use inside bracket)\n\n- Mutate the collection i.e. remove \u002F add \u002F reorder item to list in stateful widget like draggable todo list where checked items get removed (ObjectKey, ValueKey & UniqueKey)\n- Move widget from one Parent to another preserving it's state. (GlobalKey)\n- Display same Widget in multiple screens and holding its state.(GlobalKey)\n- Validate Form.(GlobalKey)\n- You can to give a key without using any data. (UniqueKey)\n- If you can use certain field of data like UUID of users as unique Key. (ValueKey)\n- If you do not have any unique field to use as key but object itself is unique. (ObjectKey)\n- If you have multiple Forms or Multiple Widgets of same type that need GlobalKey. (GlobalObjectKey, LabeledGlobalKey whichever is appropriate , similar logic to ValueKey and ObjectKey)\n\n[Learn more on this video](https:\u002F\u002Fwww.youtube.com\u002Fwatch?v=kn0EOS-ZiIc)\n\n## Tip 19 : Amazing Library `time.dart`\n\nIf you are tired to long and verbose DateTime and Duration calculation `time.dart` comes to your rescue.\n\n```dart\n\u002F\u002FBefore\nvar 3dayLater = DateTime.now().add(Duration(days: 3)).day;\n\n\u002F\u002FAfter\nvar 3dayLater = 3.days.fromNow.day;\n\n\u002F\u002FBefore\nvar duration = Duration(minutes: 10) +Duration(seconds: 15) \n  - Duration(minutes: 3) + Duration(hours: 2;\n\n\u002F\u002FAfter\nvar duration = 10.minutes + 15.seconds - 3.minutes + 2.hours;\n\n\u002F\u002FBefore\nawait  Future.delayed(Duration(seconds: 2))\n\n\u002F\u002FAfter\nawait 2.seconds.delay\n```\n[visit time.dart](https:\u002F\u002Fgithub.com\u002Fjogboms\u002Ftime.dart)\n\n## Tip 20 : Testing errors\n\nYou can simply test if two values are equal in dart with `expect(actual, expected)`\n\nBut if you want to test errors use the `function closure` that throws error as actual and check with `throwsA\u003CErrorType>` as expected.\n\n```dart\nvoid main() {\n  group(\"Exception\u002FError testing\", () {\n    test(\"test method that throws errors\", () {\n      expect(_testError(fails: false), false);\n      expect(() => _testError(fails: true), throwsA(isA\u003CFooError>()));\n    });\n  });\n}\n\nbool _testError({bool fails}) {\n  if(fails)throw FooError();\n    return fails;\n}\n\nclass FooError extends Error {}\n```\n\n[___`Tips 1-20`___](README.md)\n[__`Next >>`__](page2.md)\n\n[__`Tips 41-60`__](page3.md)\n[__`Tips 61-80`__](page4.md)\n[__`Tips 81-100`__](page5.md)\n","awesomefluttertips 是一个收集了 Flutter 开发技巧和窍门的项目。它提供了诸如通过输入 `stless` 和 `stful` 快速生成无状态和有状态小部件、使用 `??` 操作符简化空值检查以及利用级联操作符（..）实现流畅API等实用代码示例，帮助开发者提高编码效率与代码可读性。此外，该项目还展示了如何在函数内部定义函数以增强封装性，并介绍了如何借助插件为 Dart 语言添加数据类支持，包括自动生成 `copyWith()`、`fromMap()` 等常用方法。非常适合希望提升自身 Flutter 技能水平或寻找高效编程实践的前端工程师参考学习。",2,"2026-06-11 03:21:37","top_language"]