An overview of the

This is the second article on Flutter For iOS. By reading this article you will get the following information:

  • Threading and asynchrony
  • Project structure and localization
  • View controller
  • layout
  • gestures
  • The form
  • The list of
  • other

Threading and asynchrony

How to write asynchronous code

Dart has a single-threaded execution model, but also supports Isolate (a way of executing Dart code on another thread), event loops, and asynchronous programming. Unless you create an Isolate, your Dart code will always execute in the main UI thread and be driven by an event loop. The event loop of Flutter is equivalent to the main loop in iOS, that is, the Looper is bound to the main thread.

Dart’s single-threaded model doesn’t mean you have to execute everything as a blocking block that causes the UI to stall. Instead, you can use Dart’s asynchronous capabilities such as Async/AWIAT to perform asynchronous tasks.

For example, you can use asyn/await to perform network code and heavy work without UI lag.

Once the network request ends, update the UI by calling setState(), triggering the subtree of the current widget and updating the data.

The following example loads data asynchronously and displays it on ListViews:

See the next section to learn how to perform tasks in background threads and how they differ from iOS.

How do I put a task on a background thread

Thanks to Flutter’s single-threaded model and event loops, you don’t have to worry about thread management or enabling background threads. You can safely use async/await methods to perform I/O operations, such as accessing a magnetic ring or requesting a network. On the other hand, if you want to perform complex calculations and keep the CPU busy, you can Isolate tasks to avoid blocking event loops.

For iOS operations, declare methods as async methods and wait for time-consuming tasks to complete with await.

loadData() async {
  String dataURL = "https://jsonplaceholder.typicode.com/posts";
  http.Response response = await http.get(dataURL);
  setState(() {
    widgets = json.decode(response.body);
  });
}
Copy the code

This is routine for common I/O operations such as network requests and database access.

However, this can still cause the UI to hang when you’re dealing with a lot of data. In Flutter, the Isolate is used to perform time-consuming or computationally intensive tasks using the advantages of multiple CPU cores.

Deleted threads are disconnected threads that do not share any heap memory with mainlines. This means that you cannot access changes in mainlines or use setState() to renew them. Computer networks are disabled by debilitating conditions.

The following code shows a simple ISOLATE that returns data to the main thread and updates the UI.

In the code above, dataLoader() is Isolate, which executes in a separate thread. Within the ISOLATE you can perform CPU intensive tasks such as parsing JSON, or perform hectic mathematical tasks such as encryption or signal processing.

You can execute the complete code as follows:

How do network requests occur

It is very simple to request networks using the popular third-party library HTTP package in Flutter. It abstracts a lot of things that you would have to do yourself, making sending requests very simple.

To use the HTTP framework, you need to add dependencies in pubspec.yaml.

dependencies: ... HTTP: ^ 0.11.3 + 16Copy the code

To initiate a network request, add await before async method http.get().

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' ashttp; [...].  loadData()async {
    String dataURL = "https://jsonplaceholder.typicode.com/posts";
    http.Response response = await http.get(dataURL); setState(() { widgets = json.decode(response.body); }); }}Copy the code

How do I show the progress of time-consuming tasks

In iOS, when performing a time-consuming task in the background, you show progress by using UIProgressView.

In Flutter, use the ProgressIndicator component. Control its presentation by passing a Boolean flag to it, telling Flutter to update its state and hide it before and after a time-consuming task has been performed.

In the following example, the build method is split into three different methods. If showLoadingDialog() is true, render the ProgressIndicator otherwise render the ListView with data returned by the network.

Project structure, localization, dependencies, and resource management

How do I manage images in Flutter and place images in multiple resolutions

Unlike iOS, which treats images and assets as different types, Flutter has only one asset. IOS assets are stored in image.xcassert files, while Flutter assets are stored in assets files. As with iOS, assets are many types of files, not just images. For example, you can put json files in your My-Assets folder.

my-assets/data.json
Copy the code

Declare in the pubspec.yaml file:

assets:
	- my-assets/data.json
Copy the code

It can then be accessed in code using AssetBunlde:

import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('my-assets/data.json');
}
Copy the code

For images, Flutter has the same format as iOS. Images can be 1x, 2x, 3x, or any other multiple. These so-called Devicepixelratios represent the ratio of physical pixels to a single logical pixel.

Assets can be placed into any type of folder. There is no pre-defined file structure in Flutter. Declare assets in a pubspec. yaml file and Flutter will recognize them.

For example, to place my_icon. PNG into a Flutter project, you might call the folder stored in the Flutter folder images. Place the pictures of the correlation coefficients in different subfiles as follows: a

images/my_icon.png       / / Base: 1.0 x image
images/2.0x/my_icon.png  / / 2.0 x image
images/3.0x/my_icon.png  / / 3.0 x image
Copy the code

Next declare the image in pubspec.yaml

assets:
	- images/my_icon.png
Copy the code

You can now use AssetImage to return images

return AssetImage("images/a_dot_burr.jpeg");
Copy the code

Or use the Image component directly

@override
Widget build(BuildContext context) {
  return Image.asset("images/my_image.png");
}
Copy the code

Refer to Adding Assets and Images in Flutter for more details.

How do I store strings, how do I manage localization

In iOS, we use the Localizable. Strings file to manage localized strings. There is no module to handle localized strings in Flutter, so it is best to store strings as static fields in one class. As follows:

class Strings {
  static String welcomeMessage = "Welcome To Flutter";
}
Copy the code

The access mode is as follows:

Text(Strings.welcomeMessage)
Copy the code

By default, Flutter only supports English strings. If you want to support other languages, you can do this by introducing the Flutter_localIzations library. You also need to pack Dart intL to support I10N mechanisms such as date/time formatting.

dependencies:
  # ...
  flutter_localizations:
    sdk: flutter
  intl: "^ 0.15.6"
Copy the code

In order to use Flutter_localizations, localizationsDelegates and supportedLocales properties need to be specified on the App Widget.

import 'package:flutter_localizations/flutter_localizations.dart';

MaterialApp(
 localizationsDelegates: [
   // Add app-specific localization delegate[s] here
   GlobalMaterialLocalizations.delegate,
   GlobalWidgetsLocalizations.delegate,
 ],
 supportedLocales: [
    const Locale('en'.'US'), // English
    const Locale('he'.'IL'), // Hebrew
    // ... other locales the app supports].// ...
)
Copy the code

The actual localization values are contained in the proxy, and supportedLocales defines which locales to support. The above example is using a MaterialApp, it has both the basic Widget value localization GlobalWidgetsLocalizations, also has in view of the Material of the Widget MaterialWidgetsLocalizations localization. If your App uses WidgetApp, the latter is not needed. It is worth noting that both agents contain default values, but if you want to localize your App, you will need to provide one or more agents as copies of your App localization.

When the initialization is complete, WidgetsApp or MaterialApp creates a Localizationswidget for you using your specified agent. You can access the localization information for the current device at any time from LocalizationsWidget, or use window.locale.

To access localized resources, use the Localizations.of() method to access the specific localized classes provided by a given delegate. Use intl_translation to fetch the translation copy into the ARB file. Import them into your App and use them with INTL.

For more internationalization and localization see: Internationalization Guide, which includes sample code for not using INTL.

Note that resource files defined in fullter before Flutter1.0 beta2 cannot be accessed natively, and natively defined resources cannot be accessed by flutter because they are stored in an invalid file directory.

How to manage dependencies

In iOS, we add dependencies to the Podfile. Flutter uses the system built in the Dart language and the Pub package manager to operate dependencies. These tools delegate the build of native Android and iOS wrapper applications to the appropriate build system.

If you include podfiles in the iOS directory of your Flutter project, just use it to add iOS native dependencies. Declare external dependencies in Flutter using pubspec.yaml. Some useful third-party dependencies can be found on the Pub website.

View controller

What elements of a Flutter are equivalent to ViewControllers?

In iOS, a ViewController represents a part of the user interface, usually a screen or part of a screen. Multiple ViewControllers are combined to create a complex user interface and help you organize the UI part of your application. In Flutter, this job falls to the Widget. As mentioned in the navigation section, the screen is represented by the Widget because “everything is a Widget”. Use Navigator to switch between different routes to represent different screens or pages or to represent different states or render the same data.

How do I listen for iOS life cycle events

In iOS, you can override methods in ViewController to capture the view’s lifecycle, or register lifecycle callbacks in AppDelegate. Without these two concepts in the Flutter, but we can through the hookWidgetsBinding and in didChangeAppLifecycleState () method to monitor the life cycle events.

The following lifecycle events can be listened on:

  • Inactive – The application is Inactive and cannot be typed by the user. This event is valid only in iOS.
  • Paused – The application is currently unavailable and does not respond to user input, but is still running in the background.
  • Resumed – Applications are available and can respond to user input.
  • Kickbacks – Apps that are temporarily suspended. This event is valid only on Android.

See AppLifecycleStatus Documentation for more details.

layout

The FlutterUITableViewUICollectionView

Flutter uses ListView to implement iOS UITableView and UICollectionView. The implementation code is as follows:

How do I know which cell is clicked

In iOS, by implementing the tableView: didSelectRowAtIndexPath: approach to the click event of corresponding cell, in a Flutter, use contains event to handle the corresponding widget itself.

How to update ListView dynamically

In iOS, we use reloadData to refresh the table view.

In Flutter, if you update the list of widgets in setState(), you will find that the list data has not changed. This is because when setState() is called, the Flutter rendering engine looks at the widget tree to see if there have been any changes. When it reaches the ListView, it performs a == check and determines that the two ListViews are the same. Nothing has changed, so no updates are needed.

Creating a new List within the setState() method is an easy way to update the ListView. And copy the data from the old list to the new list. While this approach is simple, it is not recommended for large data sets, as shown in the following example.

We recommend using ListView.Builder to build lists, which is more efficient. This is useful when your list contains a large amount of data.

Instead of creating a ListView, creating a ListView. Builder takes two parameters: the initial length of the list and the ItemBuilder method.

The ItemBuilder method is similar to the cellForItemAt agent for table or Collection in iOS in that it carries a location and returns the cell that needs to be rendered for that location.

And last but not least, the onTap method doesn’t recreate a list, it adds a Widget.

How do I use something like ScrollView

@override
Widget build(BuildContext context) {
  return ListView(
    children: <Widget>[
      Text('Row One'),
      Text('Row Two'),
      Text('Row Three'),
      Text('Row Four'),]); }Copy the code

Gesture detection and touch event handling

How do I add an event listener to a widget

If the widget supports event handling, such as RaisedButton, the corresponding method can be passed directly to the corresponding property, such as RaisedButton’s onPressed.

Widget build(BuildContext context) {
  return RaisedButton(
    onPressed: () {
      print("click");
    },
    child: Text("Button")); }Copy the code

If the widget does not support event handling, you can wrap it around the GestureDetector and pass a method to the onTap property.

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Sample App'),
    ),
    body: Center(
      child: GestureDetector(
        child: FlutterLogo(
          size: 200,
        ),
        onTap: () {
          print('taped'); },),)); }Copy the code

How do you handle other types of events on widgets

We can use GestureDetector to listen for the following events:

  • Click on the
    • onTapDown– Press the gesture event
    • onTapUp– Lift event
    • onTap— Click events
    • onTapCancel— Cancel the click event,onTapDownOccurs, but onTap does not.
  • Double click on the
    • onDoubleTap– Double-click event
  • Long press
    • onLongPress– Long press event
  • Vertical drag
    • onVerticalDragStart– The vm starts to move vertically
    • onVerticalDragUpdate– Vertical movement is in progress.
    • onVerticalDragEnd– The vertical movement is complete.
  • Horizontal scrolling
    • onHorizontalDragStart– Start to move horizontally.
    • onHorizontalDragUpdate– Horizontal movement is in progress.
    • onHorizontalDragEnd– The horizontal movement is complete.

The following code shows how to implement a double click event using GestureDetector:

Operation effect:

Subject and text

How do I set the theme for my application

Flutter provides a set of themes that perfectly match Material Design. It handles most of the styles and themes that you need to handle yourself.

To take full advantage of the Material component in your App, declare the MaterialApp on the top-level component as the entry point to your App. MaterialApp is a convenience component that contains many Materail Desigin-style components commonly required by apps. This is done by adding MD functionality to WidgetsApp.

Flutter is also flexible and expressive enough to implement any other design language. On iOS, you can use Cupertino Library to create Human Interface Guidelines. To view a collection of these widgets, see Cupertino Widgets Gallery.

You can also use WidgetApp in your App, which provides many similar features but is not as rich as MaterialApp.

Defining colors and styles for any child component, you can pass a ThemeData object to the MaterialApp Widget. For example, in the code below, the primary swatch is set to blue and the selected color of the text is red:

class SampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, textSelectionColor: Colors.red ), home: SampleAppPage(), ); }}Copy the code

How do I use custom fonts on Text Widgets

In iOS, you introduce arbitrary TTF files into your project and set references in info.plist. In Flutter, place the font file in the folder and reference it in pubspec.yaml, just like adding images.

fonts:
   - family: MyCustomFont
     fonts:
       - asset: fonts/MyCustomFont.ttf
       - style: italic
Copy the code

Then specify the font in your Text Widget:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("Sample App"),
    ),
    body: Center(
      child: Text(
        'This is a custom font text',
        style: TextStyle(fontFamily: 'MyCustomFont'),),),); }Copy the code

How do I style a Text Widget

In addition to fonts, you can also set custom values for the style elements of Text Widgets. The Text widget accepts a TextStyle object, and you can specify a number of parameters as follows:

  • color
  • decoration
  • decorationColor
  • decorationStyle
  • fontFamily
  • fontSize
  • fontStyle
  • fontWeight
  • hashCode
  • height
  • inherit
  • letterSpacing
  • textBaseline
  • wordSpacing

Form input

How do forms work in Flutter, and how do they retrieve values entered by the user

In iOS, we usually get content from components when a user submits. With Flutter, which has immutable components that use independent states, you might wonder how to get user input.

For form operations, they are implemented through specific widgets, just like any other functionality. By using TextField or TextFormField you can retrieve the input via TextEditingController.

Example code is as follows:

Running effect

Reference for more information: The Retrieve the value of a text field by the Flutter Cookbook

How to realize the function like text input field placeholder

Implement the placeholder function for TextField by passing an InputDecoration object to the Decoration property.

body: Center(
  child: TextField(
    decoration: InputDecoration(hintText: "This is a hint"),),)Copy the code

How do I display acceptance error messages

As in the above code, you just add an errorText field to control the error message prompt through state.

Example code is as follows:

Operation effect:

Interaction with hardware, third-party services, and platforms

How do I interact with the platform and platform native code

Flutter does not run code directly on the platform. Instead, FlutterApp, built from the Dart language, runs native to the device, “circumventing” the SDK provided by the platform. For example, sending a network request in Dart is performed directly in the Dart context, not the Android or ios apis we use when writing native apps. Our FlutterApp is still held as a View by the native App ViewController, but we don’t have direct access to the ViewController or the native framework.

This does not mean that the Flutter application cannot interact with native apis or other native code you write. A Flutter provides platform channels that can communicate or exchange data with the VIewController that holds your Flutter view. Platform Channels is essentially an asynchronous communication mechanism that Bridges the Dart code with its host ViewController, the iOS framework. For example. You can use Platform Channels to perform a native function, or to fetch data from the device’s sensors.

In addition to using Platform Channels directly, you can also use a series of pre-made plugins. For example, you can use plug-ins directly to access camera film or the device’s camera without having to write your own integration layer code. You can find plug-ins at Pub, a repository of open source packages for Dart and Flutter. Some of these packages may support integration with iOS or Android, or both.

If you can’t find a plugin that meets your needs on Pub, you can write it yourself and publish it on Pub.

How do I access the GPS sensor

Use the geolocator

How to access the camera

Using image_picker

How do I log in using FaceBook

Using flutter_facebook_login

How do I use Firebase

Most Firebase features are included in First Party plugins. These first-party plug-ins are maintained by the Flutter team:

  • firebase_admob : Firebase AdMob
  • firebase_analytics : Firebase Analytics
  • firebase_auth : Firebase Auth
  • Firebase_core: Firebase’s Core package
  • firebase_database : Firebase RTDB
  • firebase_storage : Firebase Cloud Storage
  • firebase_messaging : Firebase Messaging (FCM)
  • Cloud_firestore: Firebase Cloud Firestore You can also find third-party plug-ins for Firebase at Pub.

How do I create native integration layer code

If there are platform-specific features that Flutter and community plug-ins miss, you can build your own plug-ins according to the Developing Packages and Plugins page. The plugin structure for Flutter is, in short, like the Event Bus in Android. You send a message and ask the recipient to process it and report back to you. In this case, the recipient is native code on Android or iOS.

Database and local storage

How to use UserDefaults in Flutter

In iOS, we can use UserDefaults to store key-value pairs. In Flutter, we can use the Shared Preferences plugin to display similar functionality. This plugin wraps UserDefaults and SharedPreferences on Android.

Flutter has the same functionality as Coredata.

You can use the SQFlite plugin to implement CoreData functionality in iOS.

notice

How do I set push notifications

On iOS, you need to register your app on the developer website to get push privileges. Push can be implemented using the Firebase_messaging plugin in Flutter. For more documentation on using the Firebase Cloud Messaging API, see firebase_Messaging

reference

This article mainly refers to Flutter official documentation, Flutter Chinese website. Due to typography, I used pictures to show the code in this article. If you need the source code, you can follow my official account and reply to the keyword “flutter” to get the relevant code.

This article was originally posted on wechat public account RiverLi