flutter conventions & best practices

安装量: 45
排名: #16312

安装

npx skills add https://github.com/kaakati/rails-enterprise-dev --skill Flutter

Layer-first (recommended for Clean Architecture):

lib/
├── domain/
├── data/
└── presentation/

Feature-first (alternative):

lib/
└── features/
    ├── auth/
    │   ├── domain/
    │   ├── data/
    │   └── presentation/
    └── profile/

Null Safety

// Use late for non-nullable fields initialized later
class MyController extends GetxController {
  late final UserRepository repository;

  @override
  void onInit() {
    super.onInit();
    repository = Get.find();
  }
}

// Use ? for nullable types
String? userName;

// Use ! only when absolutely certain
final name = userName!; // Use sparingly

// Prefer ?? for defaults
final displayName = userName ?? 'Guest';

Async/Await Best Practices

// Use async/await for asynchronous operations
Future<User> fetchUser(String id) async {
  try {
    final response = await client.get(Uri.parse('/users/$id'));
    return User.fromJson(jsonDecode(response.body));
  } on SocketException {
    throw NetworkException();
  } catch (e) {
    throw UnknownException(e.toString());
  }
}

// Use Future.wait for parallel operations
Future<void> loadAllData() async {
  final results = await Future.wait([
    fetchUsers(),
    fetchSettings(),
    fetchPreferences(),
  ]);
}

// Use unawaited for fire-and-forget
unawaited(analytics.logEvent('page_view'));

Code Organization Within Files

class MyClass {
  // 1. Constants
  static const int maxRetries = 3;

  // 2. Static fields
  static final instance = MyClass._();

  // 3. Instance fields
  final String id;
  final _isLoading = false.obs;

  // 4. Constructors
  MyClass(this.id);
  MyClass._();

  // 5. Getters/Setters
  bool get isLoading => _isLoading.value;

  // 6. Lifecycle methods
  @override
  void onInit() {}

  // 7. Public methods
  void publicMethod() {}

  // 8. Private methods
  void _privateMethod() {}
}

Widget Best Practices

// Prefer const constructors
class MyWidget extends StatelessWidget {
  const MyWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Text('Hello');
  }
}

// Extract widgets for reusability
class UserCard extends StatelessWidget {
  final User user;

  const UserCard({Key? key, required this.user}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Card(
      child: _buildContent(),
    );
  }

  Widget _buildContent() {
    return Column(
      children: [
        Text(user.name),
        Text(user.email),
      ],
    );
  }
}
返回排行榜