mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This updates Flutter's templates to reduce the number of changes triggered by running `dart format` immediately after `flutter create`. I will get a test exemption: this is a refactoring with no semantic changes. <details> <summary>Steps to check for stale templates...</summary> ```shell # Create a directory to test the templates rm -rf templates_test mkdir templates_test cd templates_test # Create the templates flutter create counter_app flutter create empty_app --empty flutter create my_package --template=package flutter create my_plugin --template=plugin --platforms=android,ios,linux,macos,windows flutter create my_ffi_package --template=package_ffi flutter create my_ffi_plugin --template=plugin_ffi flutter create my_module --template module # Use git to check for changes git init git add . git commit -m "Start" # Format the templates dart format . # Check for "unexpected" changes: git diff ``` </details> Part of https://github.com/flutter/flutter/issues/175960 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
139 lines
4.9 KiB
Cheetah
139 lines
4.9 KiB
Cheetah
{{#no_platforms}}
|
|
// You have generated a new plugin project without specifying the `--platforms`
|
|
// flag. An FFI plugin project that supports no platforms is generated.
|
|
// To add platforms, run `flutter create -t plugin_ffi --platforms <platforms> .`
|
|
// in this directory. You can also find a detailed instruction on how to
|
|
// add platforms in the `pubspec.yaml` at
|
|
// https://flutter.dev/to/pubspec-plugin-platforms.
|
|
{{/no_platforms}}
|
|
|
|
import 'dart:async';
|
|
import 'dart:ffi';
|
|
import 'dart:io';
|
|
import 'dart:isolate';
|
|
|
|
import '{{projectName}}_bindings_generated.dart';
|
|
|
|
/// A very short-lived native function.
|
|
///
|
|
/// For very short-lived functions, it is fine to call them on the main isolate.
|
|
/// They will block the Dart execution while running the native function, so
|
|
/// only do this for native functions which are guaranteed to be short-lived.
|
|
int sum(int a, int b) => _bindings.sum(a, b);
|
|
|
|
/// A longer lived native function, which occupies the thread calling it.
|
|
///
|
|
/// Do not call these kind of native functions in the main isolate. They will
|
|
/// block Dart execution. This will cause dropped frames in Flutter applications.
|
|
/// Instead, call these native functions on a separate isolate.
|
|
///
|
|
/// Modify this to suit your own use case. Example use cases:
|
|
///
|
|
/// 1. Reuse a single isolate for various different kinds of requests.
|
|
/// 2. Use multiple helper isolates for parallel execution.
|
|
Future<int> sumAsync(int a, int b) async {
|
|
final SendPort helperIsolateSendPort = await _helperIsolateSendPort;
|
|
final int requestId = _nextSumRequestId++;
|
|
final _SumRequest request = _SumRequest(requestId, a, b);
|
|
final Completer<int> completer = Completer<int>();
|
|
_sumRequests[requestId] = completer;
|
|
helperIsolateSendPort.send(request);
|
|
return completer.future;
|
|
}
|
|
|
|
const String _libName = '{{projectName}}';
|
|
|
|
/// The dynamic library in which the symbols for [{{pluginDartClass}}Bindings] can be found.
|
|
final DynamicLibrary _dylib = () {
|
|
if (Platform.isMacOS || Platform.isIOS) {
|
|
return DynamicLibrary.open('$_libName.framework/$_libName');
|
|
}
|
|
if (Platform.isAndroid || Platform.isLinux) {
|
|
return DynamicLibrary.open('lib$_libName.so');
|
|
}
|
|
if (Platform.isWindows) {
|
|
return DynamicLibrary.open('$_libName.dll');
|
|
}
|
|
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
|
|
}();
|
|
|
|
/// The bindings to the native functions in [_dylib].
|
|
final {{pluginDartClass}}Bindings _bindings = {{pluginDartClass}}Bindings(_dylib);
|
|
|
|
/// A request to compute `sum`.
|
|
///
|
|
/// Typically sent from one isolate to another.
|
|
class _SumRequest {
|
|
final int id;
|
|
final int a;
|
|
final int b;
|
|
|
|
const _SumRequest(this.id, this.a, this.b);
|
|
}
|
|
|
|
/// A response with the result of `sum`.
|
|
///
|
|
/// Typically sent from one isolate to another.
|
|
class _SumResponse {
|
|
final int id;
|
|
final int result;
|
|
|
|
const _SumResponse(this.id, this.result);
|
|
}
|
|
|
|
/// Counter to identify [_SumRequest]s and [_SumResponse]s.
|
|
int _nextSumRequestId = 0;
|
|
|
|
/// Mapping from [_SumRequest] `id`s to the completers corresponding to the correct future of the pending request.
|
|
final Map<int, Completer<int>> _sumRequests = <int, Completer<int>>{};
|
|
|
|
/// The SendPort belonging to the helper isolate.
|
|
Future<SendPort> _helperIsolateSendPort = () async {
|
|
// The helper isolate is going to send us back a SendPort, which we want to
|
|
// wait for.
|
|
final Completer<SendPort> completer = Completer<SendPort>();
|
|
|
|
// Receive port on the main isolate to receive messages from the helper.
|
|
// We receive two types of messages:
|
|
// 1. A port to send messages on.
|
|
// 2. Responses to requests we sent.
|
|
final ReceivePort receivePort = ReceivePort()
|
|
..listen((dynamic data) {
|
|
if (data is SendPort) {
|
|
// The helper isolate sent us the port on which we can sent it requests.
|
|
completer.complete(data);
|
|
return;
|
|
}
|
|
if (data is _SumResponse) {
|
|
// The helper isolate sent us a response to a request we sent.
|
|
final Completer<int> completer = _sumRequests[data.id]!;
|
|
_sumRequests.remove(data.id);
|
|
completer.complete(data.result);
|
|
return;
|
|
}
|
|
throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
|
|
});
|
|
|
|
// Start the helper isolate.
|
|
await Isolate.spawn((SendPort sendPort) async {
|
|
final ReceivePort helperReceivePort = ReceivePort()
|
|
..listen((dynamic data) {
|
|
// On the helper isolate listen to requests and respond to them.
|
|
if (data is _SumRequest) {
|
|
final int result = _bindings.sum_long_running(data.a, data.b);
|
|
final _SumResponse response = _SumResponse(data.id, result);
|
|
sendPort.send(response);
|
|
return;
|
|
}
|
|
throw UnsupportedError('Unsupported message type: ${data.runtimeType}');
|
|
});
|
|
|
|
// Send the port to the main isolate on which we can receive requests.
|
|
sendPort.send(helperReceivePort.sendPort);
|
|
}, receivePort.sendPort);
|
|
|
|
// Wait until the helper isolate has sent us back the SendPort on which we
|
|
// can start sending requests.
|
|
return completer.future;
|
|
}();
|