1. Do we need Flutter?
Unlike RN, Flutter doesn’t have anything to do with native iOS/Android components like UIButton. All the elements of Flutter are drawn by itself, while RN just makes a bridge call. Understand that this can be very useful for you to make decisions/fool your boss
To start, we assume that you already have some basic concepts of Flutter, such as Release/Debug versions, such as how to run a HelloWord
2. Mixed stack:
Dad’s guide here
Google makes it very clear that you can mix the two by looking for 1234567. Of course you can also Google flutter mix.
Here are a few things that dads don’t tell you about the configuration:
0.flutter create -t module xxx
The -t
There are many instances where the flutter create does not have -t. Simply put, without -t, your iOS/ Android projects will be submitted with Git and they will never be submitted. Anyone who pulls new code needs to flutter Create to run properly.
You don’t need to change any native works written with Flutter, and your iOS folder won’t be affected by SDK changes or Xcode changes, but please be honest with society:
- Default generated iOS folder
podfile
There is no! use_framwork
the - Are you sure you don’t need to change plist to add whitelist or something
- Are you sure you don’t need some configuration in the AppDelegate to assist your third-party libraries like wechat
So if -t, you as the architect/researcher should be prepared to write scripts to modify these files.
Also please run flutter Packages get properly, because it will rearrange the contents of your iOS folder, and the flutter build –release will help you get flutter packages by default, so if you have your own initialization script, The order of execution should be:
flutter packages get
- Your script
flutter build --release -no-pub
-no-pub
Will be ignoredbuild
At the time of theget
1. Build Phases
In thescript
You don’t always need to run
Flutter Release
- To put it bluntly, if you just debug the script without running it, the results are the same
Flutter Debug
model - This script increases compilation time, so no need
flutter
The update engineer doesn’t need to care if he runs away - If you are
Debug
The main project wants to runRelease
theFlutter
If you don’t run this Script will crash, that’s whyFlutter Release
Configuration requires this script to complete
2. Be honest and follow Google’s recommendations. Your goal is to run and quickly get familiar with dart andflutter
Layout is not a study of native withflutter
And frame coupling
3. In the package scriptFlutter run
Is not reasonable
You may also use Jenkins or Fastlane to pack QA. If you want to generate products, go to the build –release command of Flutter because Flutter run will directly freeze the process and you will not be able to continue. Although you can choose to run in the background, But you can’t guarantee synchronization
4. Jump or walkflutter_boost
As for why, you can turn over the article written by salted fish, or from the simplified that is:
- In Google’s stack of Flutter blends,
FlutterViewController
In the bellyFlutter engine
So if you have a pure Flutter project you will notice that there is only one VC, and he draws new pages in a single VC to complete the push operation - But in the mix stack you definitely will
FlutterViewController
Push the next oneFlutterViewController
“, which will cause your application to crash in a matter of time - The salted fish solution is to keep one engine, then take the engine singleton from the previous VC to the next while pushing, and then reproduce the slide back or pop via screenshots and so on
Of course, if you are the kind of very good must play by yourself, that is also ok, otherwise see 2 said in here also applies ~
Query: {“query”: {“name” : XXX}} {“query”: {“name” : XXX}}} {“query”: {“name” : XXX}}} {“query”: {“name” : XXX}}}} {“query”: {“name” : XXX}}
5. MethodChannel series interactions
For normal interactive registration, you can click here. It’s very simple
The FlutterPlugin is an elegant pose, though it’s officially recommended
I am an elegant 🌰
To be clear, MethodChannel just needs to have a chance to register with the Flutter engine at any time, so we found the time for FlutterPlugin. All third-party flutter plugin (which most is part of a native calling through the channel to solve), actually also is injected into the engine by means of registered, if you want to see how come, you can find in your project GeneratedPluginRegistrant. M this file, This is a system-generated file that will help you register all the plug-ins you have introduced into Flutter:
@implementation GeneratedPluginRegistrant + (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry { [FLTDeviceInfoPlugin registerWithRegistrar:[registry registrarForPlugin:@"FLTDeviceInfoPlugin"]]; . } @endCopy the code
So we had a bold idea. If we could build a plugin of our own, with a channel in it, that would allow all the flutter to interact with our existing main project, wouldn’t it be elegant? But the problem is that: the system generated GeneratedPluginRegistrant how do I add my own plug-in inside? Because my own mods are in the main project, not introduced in Flutter…
By this time you might have thought of the dark magic that was forgotten during the Swift era:
- (instancetype)init
{
if (self = [super init]) {
_viewController = [FLBFlutterViewControllerAdaptor new];
[_viewController view];
Class clazz = NSClassFromString(@"GeneratedPluginRegistrant");
if (clazz) {
if ([clazz respondsToSelector:NSSelectorFromString(@"registerWithRegistry:")]) {
[clazz performSelector:NSSelectorFromString(@"registerWithRegistry:")
withObject:_viewController];
}
}
}
return self;
}
Copy the code
The above is to find the flutter_boost, so you should know that in fact you can also to steal the registerWithRegistry GeneratedPluginRegistrant method to register first flutter own plugin. Re-registering the main project plugin has maintained a graceful posture ~
6. What should I communicate with native
The FlutterResult class specifies that a String should be passed, so please repeat this sentence. Do not make a data into a String and then pass it to flutter to change it back to data or even image. Remember, You can’t read the image string, and neither can Flutter. Json strings can be read by you, so can flutter
So for complex files, just know that Flutter can’t read data, but it can also access NSTemporaryDirectory, so you can support both parties to share the same data with a temporary folder path. This is not recommended, but it seems to be the best you can do
private func saveToFile(image: UIImage) -> String? { guard let data = image.jpg(compressionQuality: Else {return nil} let tempDir = NSTemporaryDirectory() let imageName = "image_picker_\(ProcessInfo().globallyUniqueString).jpg" let filePath = tempDir.appending(imageName) if FileManager.default.createFile(atPath: filePath, contents: data, attributes: nil) { return filePath } else { return nil } }Copy the code
Like this upstairs
3. Dart
What do I need to prepare
1. Abstract the underlying services
If the initial planning is to make the underlying services native, such as request login to take photos and so on, then ideally you can actually feel that the flutter code is all you need to do with the business.
Well, think back to you in RN who coded for 5 minutes and logged for 5 hours? So if you have time, please build all the infrastructure you can for Flutter to speed up debugging dramatically:
The following pattern can be used to maximize code extensibility
We’re through
God mode: isSonMode= false indicates the mode of flutter to run by itself
Son mode: isSonMode= true which is run mode in main project
This distinction is used to determine which underlying service we need to invoke
For example here is our DART side request call:
class RequestService { static RequestService shared = RequestService(); factory RequestService() => GlobalConfig.isSonMode ? SonRequestService() : GodRequestService(); Future<Map> Post (String URL, Map para) async {throw UnimplementedError("saveElement method is not implemented "); } Future<UploadItem> upload(UploadItem file) async {throw UnimplementedError("saveElement method is not implemented "); } } class GodRequestService implements RequestService { Future<Map> post(String url, Map para) async {// You can call dio or HTTP request here} Future<UploadItem> upload(UploadItem file) async {... }}Copy the code
We use globalConfig. isSonMode to switch between specific RequestService implementations to isolate each RequestService from contamination.
There are, of course, fancier judgments:
static Router _route =
GlobalConfig.isAndroid ? AndroidRouteBox() : GlobalConfig.isSonMode ? FlutterBoostRouteBox() : GodRouteBox();
Copy the code
For example, for routing, flutter jump is used in the mode of Flutter God, flutter_boost is used in the iOS main project, and flutter jump is still used in the android main project
And you only need to do in the dart business code RequestService. Shared. Post… Can be normal request, do not need to care about the problem of switching.
(Of course, request abstraction will be covered in the next installment, so stay tuned.)
2. Model.fromJSON
Tools are everywhere and a little bit recommended for this one, which of course is extremely complimentary to handwriting perseverance ~ but note:
dart
Compared with theSwift
Is more strict about the typeint
/double
If the definition is reversed, it will explode1.0
To pass toint
Type attribute, inSwift
In no waves, indart
In the middle of the waves,dart
A medium point can be usednum
To modify all the numbersString
Both types are recommendedtoString()
Plus an elegant one from Swift
var isUser : Dart: Bool {return XXX == 1 &&xxxx = 2} Bool get isUser => XXX == 1 && XXXX = 2 or bool get isUser {return XXX == 1 && XXXX = 2}Copy the code
This will reduce the amount of business computation in your Widget; let the Model do the defining
Forget about the page life cycle
Because the engine is drawn differently, the page life cycle of flutter does not have the right callbacks/proxies to trigger it. Don’t think of making strange requests to refresh in didUpdateWidget or Dependency. That’s not a place for you to do that. The only thing you can do seems to be do everything in initState;
This is a bit virtual, so all actions need to be triggered strictly from actions, not from the page level,
For example
Swift: Button Click -> Jump -> Back -> ViewWillAppear to refresh the whole page
Flutter: button Click -> refresh the corresponding Widget -> jump
In fact examples of Swift, also is not good, but actually we do it because of lazy basic, but we can’t know the page life cycle in the dart, so please use the right time to do the right thing, of course this would tolerate the screen full of setState, will surely someone told you that it is not reasonable ~ how to reasonable, here aside, After all, the goal here is to get the app running and online, as for elegant or not elegant behind the familiar will naturally have a feeling.
4. Resource pictures
In pubspec.yaml this will do
Assets: -assets /images/ -assets /images/2.0x/ -assets /images/3.0x/Copy the code
Sometimes you will find that you add a new picture and the result is put in the right position, but the result does not come out. It is ok that you debug it several times and it will come out. If you confirm that there is no problem with the name, it may not be displayed in time sometimes
5. The font
The interesting thing is that for the main entry:
Return MaterialApp(Title: 'I'm a demo', theme: ThemeData(fontFamily: platform.isios? 'PingFang SC' : null,) }Copy the code
You need to do this to make your font look good on iOS phones, otherwise it will look all kinds of weird, but there is a hidden pit:
The top widget on all your pages has to be in the Material family for this to work, these are the Material family,
So if your page says:
class DemoPage extends StatelessWidget { @override Widget build(BuildContext context) { return Container( child: Page elements); }}Copy the code
You’ll notice that your fonts are still weird, even though the page looks fine
Is not very simple, see here, pit certainly still have, but at least the big problem should be gone, you should be able to run your application happily ~