8000 Android Embedding PR 14: Almost done with FlutterFragment. (#8000) · flutter/engine@8f1fdcd · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 8f1fdcd

Browse files
Android Embedding PR 14: Almost done with FlutterFragment. (#8000)
1 parent fb3e35d commit 8f1fdcd

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

shell/platform/android/io/flutter/embedding/engine/android/FlutterFragment.java

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import io.flutter.embedding.engine.FlutterEngine;
2020
import io.flutter.embedding.engine.FlutterShellArgs;
2121
import io.flutter.embedding.engine.dart.DartExecutor;
22+
import io.flutter.plugin.platform.PlatformPlugin;
2223
import io.flutter.view.FlutterMain;
2324

2425
import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
@@ -160,6 +161,8 @@ protected static Bundle createArgsBundle(@Nullable String dartEntrypoint,
160161
private FlutterEngine flutterEngine;
161162
@Nullable
162163
private FlutterView flutterView;
164+
@Nullable
165+
private PlatformPlugin platformPlugin;
163166

164167
public FlutterFragment() {
165168
// Ensure that we at least have an empty Bundle of arguments so that we don't
@@ -181,11 +184,30 @@ public FlutterEngine getFlutterEngine() {
181184
public void onAttach(Context context) {
182185
super.onAttach(context);
183186

187+
initializeFlutter(getContextCompat());
188+
184189
// When "retain instance" is true, the FlutterEngine will survive configuration
185190
// changes. Therefore, we create a new one only if one does not already exist.
186191
if (flutterEngine == null) {
187192
createFlutterEngine();
188193
}
194+
195+
// Regardless of whether or not a FlutterEngine already existed, the PlatformPlugin
196+
// is bound to a specific Activity. Therefore, it needs to be created and configured
197+
// every time this Fragment attaches to a new Activity.
198+
// TODO(mattcarroll): the PlatformPlugin needs to be reimagined because it implicitly takes
199+
// control of the entire window. This is unacceptable for non-fullscreen
200+
// use-cases.
201+
platformPlugin = new PlatformPlugin(getActivity(), flutterEngine.getPlatformChannel());
202+
}
203+
204+
private void initializeFlutter(@NonNull Context context) {
205+
String[] flutterShellArgsArray = getArguments().getStringArray(ARG_FLUTTER_INITIALIZATION_ARGS);
206+
FlutterShellArgs flutterShellArgs = new FlutterShellArgs(
207+
flutterShellArgsArray != null ? flutterShellArgsArray : new String[] {}
208+
);
209+
210+
FlutterMain.ensureInitializationComplete(context.getApplicationContext(), flutterShellArgs.toArray());
189211
}
190212

191213
/**
@@ -307,7 +329,72 @@ protected String getDartEntrypointFunctionName() {
307329
// TODO(mattcarroll): determine why this can't be in onResume(). Comment reason, or move if possible.
308330
public void onPostResume() {
309331
Log.d(TAG, "onPostResume()");
310-
flutterEngine.getLifecycleChannel().appIsResumed();
332+
if (flutterEngine != null) {
333+
flutterEngine.getLifecycleChannel().appIsResumed();
334+
335+
// TODO(mattcarroll): find a better way to handle the update of UI overlays than calling through
336+
// to platformPlugin. We're implicitly entangling the Window, Activity, Fragment,
337+
// and engine all with this one call.
338+
platformPlugin.onPostResume();
339+
340+
// TODO(mattcarroll): consider a more abstract way to invoke this behavior. It is very strange for
341+
// a Fragment to have a seemingly random View responsibility, but this is what
342+
// existed in the original embedding and I don't have a good alternative yet.
343+
flutterView.updateAccessibilityFeatures();
344+
} else {
345+
Log.w(TAG, "onPostResume() invoked before FlutterFragment was attached to an Activity.");
346+
}
347+
}
348+
349+
@Override
350+
public void onPause() {
351+
super.onPause();
352+
Log.d(TAG, "onPause()");
353+
flutterEngine.getLifecycleChannel().appIsInactive();
354+
}
355+
356+
@Override
357+
public void onStop() {
358+
super.onStop();
359+
Log.d(TAG, "onStop()");
360+
flutterEngine.getLifecycleChannel().appIsPaused();
361+
}
362+
363+
@Override
364+
public void onDestroyView() {
365+
super.onDestroyView();
366+
Log.d(TAG, "onDestroyView()");
367+
flutterView.detachFromFlutterEngine();
368+
}
369+
370+
@Override
371+
public void onDetach() {
372+
super.onDetach();
373+
Log.d(TAG, "onDetach()");
374+
375+
// Null out the platformPlugin to avoid a possible retain cycle between the plugin, this Fragment,
376+
// and this Fragment's Activity.
377+
platformPlugin = null;
378+
379+
// Destroy our FlutterEngine if we're not set to retain it.
380+
if (!retainFlutterIsolateAfterFragmentDestruction()) {
381+
flutterEngine.destroy();
382+
flutterEngine = null;
383+
}
384+
}
385+
386+
/**
387+
* Returns true if the {@link FlutterEngine} within this {@code FlutterFragment} should outlive
388+
* the {@code FlutterFragment}, itself.
389+
*
390+
* Defaults to false. This method can be overridden in subclasses to retain the
391+
* {@link FlutterEngine}.
392+
*/
393+
// TODO(mattcarroll): consider a dynamic determination of this preference based on whether the
394+
// engine was created automatically, or if the engine was provided manually.
395+
// Manually provided engines should probably not be destroyed.
396+
protected boolean retainFlutterIsolateAfterFragmentDestruction() {
397+
return false;
311398
}
312399

313400
/**

shell/platform/android/io/flutter/embedding/engine/android/FlutterView.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import android.graphics.Rect;
1010
import android.os.Build;
1111
import android.os.LocaleList;
12+
import android.provider.Settings;
1213
import android.support.annotation.NonNull;
1314
import android.support.annotation.Nullable;
1415
import android.text.format.DateFormat;
@@ -334,6 +335,15 @@ public boolean onHoverEvent(MotionEvent event) {
334335
}
335336
//-------- End: Process UI I/O that Flutter cares about. ---------< 7F90 /span>
336337

338+
//-------- Start: Accessibility -------
339+
/**
340+
* No-op. Placeholder so that the containing Fragment can call through, but not yet implemented.
341+
*/
342+
public void updateAccessibilityFeatures() {
343+
// TODO(mattcarroll): bring in accessibility code from old FlutterView.
344+
}
345+
//-------- End: Accessibility ---------
346+
337347
/**
338348
* Connects this {@code FlutterView} to the given {@link FlutterEngine}.
339349
*

0 commit comments

Comments
 (0)
0