What happened between clicking on the desktop icon and showing the first frame of Flutter with a display page in between? This paper analyzes flutter based on the Android platform. First, the startup effect of Flutter is shown as follows:

Create an analysis demo

Start AndroidStudio, File-> New -> New Flutter Project -> New Flutter Application, then enter the Project name hello_flutter, click next, enter your package name, Then click Finish to create the sample program. The default file structure is as follows:

hello_flutter
	-.ides
	-android
		-app/src/main
		-gradle
	-ios
	-lib
	-test
	-pubspec.yaml
Copy the code

The startup effect of clicking icon is roughly similar to that of the town building map. We will analyze it based on the startup code below.

AndroidManifest.xml

Based on the previous knowledge, Flutter generates a FlutterView and adds it to the Activity’s container view when it is run on Android. Since it is based on Android, the launch entry must be configured in androidmanifest.xml.

<application
    android:name="io.flutter.app.FlutterApplication"
    android:label="hello_flutter"
    android:icon="@mipmap/ic_launcher">
    <activity
        android:name=".MainActivity"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:hardwareAccelerated="true"
        android:windowSoftInputMode="adjustResize"> <! -- This keeps the window background of the activity showing until Flutter renders its first frame. It can be removedif
             there is no splash screen (such as the default splash screen
             defined in@style/LaunchTheme). --> <meta-data android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
            android:value="true" />
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
</application>
Copy the code

According to note 1, the images displayed on the flutter startup page can be modified. This article will not go into details. Another article about the Flutter startup page will be written later. Given that MainActivity is our startup entry, let’s take a look.

public class MainActivity extends FlutterActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); }}Copy the code

Inheriting FlutterActivity, let’s see what onCreate does that inherits FlutterActivity:

public class FlutterActivity extends Activity implements Provider, PluginRegistry, ViewFactory {
    private static final String TAG = "FlutterActivity";
    private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
    private final FlutterActivityEvents eventDelegate;
    private final Provider viewProvider;
    private final PluginRegistry pluginRegistry;

    public FlutterActivity() { this.eventDelegate = this.delegate; this.viewProvider = this.delegate; this.pluginRegistry = this.delegate; }... protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.eventDelegate.onCreate(savedInstanceState); // Comment 2}... }Copy the code

Note 2: eventDelegate is a FlutterActivityDelegate, and its onCreate source code is as follows:

public void onCreate(Bundle savedInstanceState) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = activity.getWindow();
        window.addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(0x40000000);
        window.getDecorView().setSystemUiVisibility(PlatformPlugin.DEFAULT_SYSTEM_UI);
    }

    String[] args = getArgsFromIntent(this.activity.getIntent());
    FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
    this.flutterView = this.viewFactory.createFlutterView(this.activity);
    if(this.flutterView == null) {// Implements the BinaryMessenger interface, Can be used to flutter and two-way communication native FlutterNativeView nativeView = this. ViewFactory. CreateFlutterNativeView (); This. flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView); // Create flutterView and add it to the activity. this.flutterView.setLayoutParams(matchParent); this.activity.setContentView(this.flutterView); this.launchView = this.createLaunchView(); // Create a LaunchView, which is the focus of our startup processif(this.launchView ! = null) { this.addLaunchView(); // Add LaunchView()}}if(! this.loadIntent(this.activity.getIntent())) { String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());if(appBundlePath ! = null) { this.runBundle(appBundlePath); } } } private ViewcreateLaunchView() {
    if(! this.showSplashScreenUntilFirstFrame()) {return null;
    } else{// Generate a drawable based on the windowBackground in the activity's theme and set it to the view. I'm not going to expand on this because I'm running out of space. Drawable launchScreenDrawable = this.getLaunchScreenDrawableFromActivityTheme();if (launchScreenDrawable == null) {
            return null;
        } else {
            View view = new View(this.activity);
            view.setLayoutParams(matchParent);
            view.setBackground(launchScreenDrawable);
            return view;
        }
    }
}

private void addLaunchView() {
    if(this.launchView ! = null) {// Set the activity to an extra Content View, which is added to the flutterView on the existing object after the existing view. this.activity.addContentView(this.launchView, matchParent); // Set a callback to FlutterView so that the LaunchView animation fades out when the first frame is displayed, and then removes it. this.flutterView.addFirstFrameListener(newFirstFrameListener() {
            public void onFirstFrame() {FlutterActivityDelegate. This. LaunchView. The animate (), alpha (0.0 F) setListener (newAnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { ((ViewGroup)FlutterActivityDelegate.this.launchView.getParent()).removeView(FlutterActivityDelegate.this.launchView); FlutterActivityDelegate.this.launchView = null; }}); FlutterActivityDelegate.this.flutterView.removeFirstFrameListener(this); }}); this.activity.setTheme(android.R.style.Theme_Black_NoTitleBar); }} /* * This corresponds to the configuration in AndroidMenifest, if the setting istrue, just want to display a launch page before displaying the first frame of Flutter. */ private BooleanshowSplashScreenUntilFirstFrame() {
    try {
        ActivityInfo activityInfo = this.activity.getPackageManager().getActivityInfo(this.activity.getComponentName(), 129);
        Bundle metadata = activityInfo.metaData;
        returnmetadata ! = null && metadata.getBoolean("io.flutter.app.android.SplashScreenUntilFirstFrame");
    } catch (NameNotFoundException var3) {
        return false; }}Copy the code

The notes are more clear, and the general process is believed to have been understood after reading the notes. Conclusion: Click the Icon to start – > MainActivity. OnCreate – > FlutterActivity. OnCreate – > FlutterActivityDelegate. OnCreate – > create and add FlutterView -> Add additional LauncherView-> FlutterView Settings listener, remove LauncherView before the first frame is displayed -> Show FlutterView

Stay tuned for a future article on Flutter Splashpage.


If you think this article is useful to you, please share and like it. Thanks a million.