接着上篇分析,这篇从FlutterActivity创建开始切入。
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
首先可以看出,默认创建的MainActivity 没有我们常见的setContentView()
,那应该是在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;
}
public FlutterView getFlutterView() {
return this.viewProvider.getFlutterView();
}
public FlutterView createFlutterView(Context context) {
return null;
}
public FlutterNativeView createFlutterNativeView() {
return null;
}
public boolean retainFlutterNativeView() {
return false;
}
public final boolean hasPlugin(String key) {
return this.pluginRegistry.hasPlugin(key);
}
public final <T> T valuePublishedByPlugin(String pluginKey) {
return this.pluginRegistry.valuePublishedByPlugin(pluginKey);
}
public final Registrar registrarFor(String pluginKey) {
return this.pluginRegistry.registrarFor(pluginKey);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.eventDelegate.onCreate(savedInstanceState);
}
protected void onStart() {
super.onStart();
this.eventDelegate.onStart();
}
protected void onResume() {
super.onResume();
this.eventDelegate.onResume();
}
protected void onDestroy() {
this.eventDelegate.onDestroy();
super.onDestroy();
}
public void onBackPressed() {
if(!this.eventDelegate.onBackPressed()) {
super.onBackPressed();
}
}
protected void onStop() {
this.eventDelegate.onStop();
super.onStop();
}
protected void onPause() {
super.onPause();
this.eventDelegate.onPause();
}
protected void onPostResume() {
super.onPostResume();
this.eventDelegate.onPostResume();
}
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
this.eventDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(!this.eventDelegate.onActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
protected void onNewIntent(Intent intent) {
this.eventDelegate.onNewIntent(intent);
}
public void onUserLeaveHint() {
this.eventDelegate.onUserLeaveHint();
}
public void onTrimMemory(int level) {
this.eventDelegate.onTrimMemory(level);
}
public void onLowMemory() {
this.eventDelegate.onLowMemory();
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
this.eventDelegate.onConfigurationChanged(newConfig);
}
}
可以看出FlutterActivity
也没有setContentView()
,并且创建FlutterView
也是为null,那么核心逻辑应该在FlutterActivityDelegate
。
FlutterActivityDelegate.class
public void onCreate(Bundle savedInstanceState) {
if(VERSION.SDK_INT >= 21) {
Window window = this.activity.getWindow();
window.addFlags(-2147483648);
window.setStatusBarColor(1073741824);
window.getDecorView().setSystemUiVisibility(1280);
}
String[] args = getArgsFromIntent(this.activity.getIntent());
FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
this.flutterView = this.viewFactory.createFlutterView(this.activity);
if(this.flutterView == null) {
FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
this.flutterView.setLayoutParams(matchParent);
this.activity.setContentView(this.flutterView);
this.launchView = this.createLaunchView();
if(this.launchView != null) {
this.addLaunchView();
}
}
if(!this.loadIntent(this.activity.getIntent())) {
String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
if(appBundlePath != null) {
this.runBundle(appBundlePath);
}
}
}
- 有个关键的方法
FlutterMain.ensureInitializationComplete()
,下面分析。 - 接着看创建FlutterView。
this.viewFactory.createFlutterNativeView()
最终来到FlutterActivity.createFlutterNativeView()
,结果返回的为null,所以FlutterNativeView的创建是在FlutterView中,下面分析。 - 创建了flutterView后,用了
setContentView(this.flutterView)
,所以整个activity的布局就是一个surfaceView - 运行的方法
this.runBundle(appBundlePath);
,最后分析。
FlutterMain.ensureInitializationComplete()
FlutterMain.class
public static void ensureInitializationComplete(Context applicationContext, String[] args) {
if(Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("ensureInitializationComplete must be called on the main thread");
} else if(sSettings == null) {
throw new IllegalStateException("ensureInitializationComplete must be called after startInitialization");
} else if(!sInitialized) {
try {
sResourceExtractor.waitForCompletion();
List<String> shellArgs = new ArrayList();
shellArgs.add("--icu-symbol-prefix=_binary_icudtl_dat");
if(args != null) {
Collections.addAll(shellArgs, args);
}
if(sIsPrecompiledAsSharedLibrary) {
shellArgs.add("--aot-shared-library-path=" + new File(PathUtils.getDataDirectory(applicationContext), sAotSharedLibraryPath));
} else {
if(sIsPrecompiledAsBlobs) {
shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext));
} else {
shellArgs.add("--cache-dir-path=" + PathUtils.getCacheDirectory(applicationContext));
shellArgs.add("--aot-snapshot-path=" + PathUtils.getDataDirectory(applicationContext) + "/" + sFlutterAssetsDir);
}
shellArgs.add("--vm-snapshot-data=" + sAotVmSnapshotData);
shellArgs.add("--vm-snapshot-instr=" + sAotVmSnapshotInstr);
shellArgs.add("--isolate-snapshot-data=" + sAotIsolateSnapshotData);
shellArgs.add("--isolate-snapshot-instr=" + sAotIsolateSnapshotInstr);
}
if(sSettings.getLogTag() != null) {
shellArgs.add("--log-tag=" + sSettings.getLogTag());
}
String appBundlePath = findAppBundlePath(applicationContext);
String appStoragePath = PathUtils.getFilesDir(applicationContext);
String engineCachesPath = PathUtils.getCacheDirectory(applicationContext);
nativeInit(applicationContext, (String[])shellArgs.toArray(new String[0]), appBundlePath, appStoragePath, engineCachesPath);
sInitialized = true;
} catch (Exception var6) {
Log.e("FlutterMain", "Flutter initialization failed.", var6);
throw new RuntimeException(var6);
}
}
}
方法作用在创建FlutterView之前先确保FlutterMain初始化完成,就是FlutterMain.startInitialization()
要完成,关于此方法分析见上文。
关键的检查方法是sResourceExtractor.waitForCompletion();
,在资源初始化完成后进行nativeInit
,此时调用了C++层的方法init
,开始初始化。
FlutterView
接着if(this.flutterView == null) 的判断,这里需要创建FlutterView。
FlutterView不是直接继承View,而是SurfaceView,相关知识可以自行搜索。
android SurfaceView 详解
FlutterView.class
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
super(context, attrs);
this.nextTextureId = new AtomicLong(0L);
this.mIsSoftwareRenderingEnabled = false;
this.mAccessibilityEnabled = false;
this.mTouchExplorationEnabled = false;
this.mAccessibilityFeatureFlags = 0;
Activity activity = (Activity)this.getContext();
if(nativeView == null) {
this.mNativeView = new FlutterNativeView(activity.getApplicationContext());
} else {
this.mNativeView = nativeView;
}
this.dartExecutor = new DartExecutor(this.mNativeView.getFlutterJNI());
this.mNativeView.getFlutterJNI();
this.mIsSoftwareRenderingEnabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled();
this.mAnimationScaleObserver = new FlutterView.AnimationScaleObserver(new Handler());
this.mMetrics = new FlutterView.ViewportMetrics();
this.mMetrics.devicePixelRatio = context.getResources().getDisplayMetrics().density;
this.setFocusable(true);
this.setFocusableInTouchMode(true);
this.mNativeView.attachViewAndActivity(this, activity);
this.mSurfaceCallback = new Callback() {
public void surfaceCreated(SurfaceHolder holder) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceChanged(width, height);
}
public void surfaceDestroyed(SurfaceHolder holder) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceDestroyed();
}
};
this.getHolder().addCallback(this.mSurfaceCallback);
this.mAccessibilityManager = (AccessibilityManager)this.getContext().getSystemService("accessibility");
this.mActivityLifecycleListeners = new ArrayList();
this.mFirstFrameListeners = new ArrayList();
this.navigationChannel = new NavigationChannel(this.dartExecutor);
this.keyEventChannel = new KeyEventChannel(this.dartExecutor);
this.lifecycleChannel = new LifecycleChannel(this.dartExecutor);
this.systemChannel = new SystemChannel(this.dartExecutor);
this.settingsChannel = new SettingsChannel(this.dartExecutor);
this.mFlutterLocalizationChannel = new MethodChannel(this, "flutter/localization", JSONMethodCodec.INSTANCE);
PlatformPlugin platformPlugin = new PlatformPlugin(activity);
MethodChannel flutterPlatformChannel = new MethodChannel(this, "flutter/platform", JSONMethodCodec.INSTANCE);
flutterPlatformChannel.setMethodCallHandler(platformPlugin);
this.addActivityLifecycleListener(platformPlugin);
this.mImm = (InputMethodManager)this.getContext().getSystemService("input_method");
this.mTextInputPlugin = new TextInputPlugin(this);
this.androidKeyProcessor = new AndroidKeyProcessor(this.keyEventChannel);
this.setLocales(this.getResources().getConfiguration());
this.sendUserPlatformSettingsToDart();
}
在onCreate()
比较关键的有
- 创建FlutterNativeView
- 初始化
DartExecutor
,JNI的创建在下面FlutterNativeView提到。 - 设置surfaceView的回调,通过FlutterJNI使得与Java层和dart层的状态同步。
- 创建系统的native插件,关于插件的分析会另起一文。
FlutterNativeView
FlutterNativeView不是View,它是与C++层进行消息传递的媒介,实现了BinaryMessenger
,二进制消息传递方法。
public interface BinaryMessenger {
void send(String var1, ByteBuffer var2);
void send(String var1, ByteBuffer var2, BinaryMessenger.BinaryReply var3);
void setMessageHandler(String var1, BinaryMessenger.BinaryMessageHandler var2);
public interface BinaryReply {
void reply(ByteBuffer var1);
}
public interface BinaryMessageHandler {
void onMessage(ByteBuffer var1, BinaryMessenger.BinaryReply var2);
}
}
由类源码可知,定义消息发送、处理消息、设置消息处理器、响应消息的接口或者方法。在FlutterNativeView实现。
FlutterNativeView.class
public FlutterNativeView(Context context) {
this(context, false);
}
public FlutterNativeView(Context context, boolean isBackgroundView) {
this.mNextReplyId = 1;
this.mPendingReplies = new HashMap();
this.mContext = context;
this.mPluginRegistry = new FlutterPluginRegistry(this, context);
this.mFlutterJNI = new FlutterJNI();
this.mFlutterJNI.setRenderSurface(new FlutterNativeView.RenderSurfaceImpl());
this.mFlutterJNI.setPlatformMessageHandler(new FlutterNativeView.PlatformMessageHandlerImpl());
this.mFlutterJNI.addEngineLifecycleListener(new FlutterNativeView.EngineLifecycleListenerImpl());
this.attach(this, isBackgroundView);
this.assertAttached();
this.mMessageHandlers = new HashMap();
}
可知
- 创建了插件的注册者
- 创建了
FlutterJNI
用于与C++层进行交互 - 关键方法
attach(this, isBackgroundView);
FlutterNativeView.attach()
FlutterNativeView.class
private void attach(FlutterNativeView view, boolean isBackgroundView) {
this.mFlutterJNI.attachToNative(isBackgroundView);
}
FlutterJNI.class
@UiThread
public void attachToNative(boolean isBackgroundView) {
this.ensureNotAttachedToNative();
this.nativePlatformViewId = Long.valueOf(this.nativeAttach(this, isBackgroundView));
}
private native long nativeAttach(FlutterJNI var1, boolean var2);
最终会调用C++层的AttachJNI()
static jlong AttachJNI(JNIEnv* env,
jclass clazz,
jobject flutterJNI,
jboolean is_background_view) {
fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
auto shell_holder = std::make_unique<AndroidShellHolder>(
FlutterMain::Get().GetSettings(), java_object, is_background_view);
if (shell_holder->IsValid()) {
return reinterpret_cast<jlong>(shell_holder.release());
} else {
return 0;
}
}
attach成功后会返回nativePlatformViewId
,用于标志attach过,供一些方法可用于检查。
private void ensureNotAttachedToNative() {
if(this.nativePlatformViewId != null) {
throw new RuntimeException("Cannot execute operation because FlutterJNI is attached to native.");
}
}
private void ensureAttachedToNative() {
if(this.nativePlatformViewId == null) {
throw new RuntimeException("Cannot execute operation because FlutterJNI is not attached to native.");
}
}
至此,Java层初始化核心逻辑大致说完,还剩下一个运行的方法。
FlutterActivityDelegate.runBundle(appBundlePath)
FlutterActivityDelegate.class
public void onCreate(Bundle savedInstanceState) {
if(VERSION.SDK_INT >= 21) {
Window window = this.activity.getWindow();
window.addFlags(-2147483648);
window.setStatusBarColor(1073741824);
window.getDecorView().setSystemUiVisibility(1280);
}
String[] args = getArgsFromIntent(this.activity.getIntent());
FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
this.flutterView = this.viewFactory.createFlutterView(this.activity);
if(this.flutterView == null) {
FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
this.flutterView.setLayoutParams(matchParent);
this.activity.setContentView(this.flutterView);
this.launchView = this.createLaunchView();
if(this.launchView != null) {
this.addLaunchView();
}
}
if(!this.loadIntent(this.activity.getIntent())) {
String appBundlePath = FlutterMain.findAppBundlePath(this.activity.getApplicationContext());
if(appBundlePath != null) {
this.runBundle(appBundlePath);
}
}
}
FlutterActivityDelegate.class
private void runBundle(String appBundlePath) {
if(!this.flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
ArrayList<String> bundlePaths = new ArrayList();
ResourceUpdater resourceUpdater = FlutterMain.getResourceUpdater();
if(resourceUpdater != null) {
File patchFile = resourceUpdater.getInstalledPatch();
JSONObject manifest = resourceUpdater.readManifest(patchFile);
if(resourceUpdater.validateManifest(manifest)) {
bundlePaths.add(patchFile.getPath());
}
}
bundlePaths.add(appBundlePath);
args.bundlePaths = (String[])bundlePaths.toArray(new String[0]);
args.entrypoint = "main";
this.flutterView.runFromBundle(args);
}
}
FlutterView.class
public void runFromBundle(FlutterRunArguments args) {
this.assertAttached();
this.preRun();
this.mNativeView.runFromBundle(args);
this.postRun();
}
FlutterNativeView.class
public void runFromBundle(FlutterRunArguments args) {
boolean hasBundlePaths = args.bundlePaths != null && args.bundlePaths.length != 0;
if(args.bundlePath == null && !hasBundlePaths) {
throw new AssertionError("Either bundlePath or bundlePaths must be specified");
} else if((args.bundlePath != null || args.defaultPath != null) && hasBundlePaths) {
throw new AssertionError("Can't specify both bundlePath and bundlePaths");
} else if(args.entrypoint == null) {
throw new AssertionError("An entrypoint must be specified");
} else {
if(hasBundlePaths) {
this.runFromBundleInternal(args.bundlePaths, args.entrypoint, args.libraryPath);
} else {
this.runFromBundleInternal(new String[]{args.bundlePath, args.defaultPath}, args.entrypoint, args.libraryPath);
}
}
}
FlutterNativeView.class
private void runFromBundleInternal(String[] bundlePaths, String entrypoint, String libraryPath) {
this.assertAttached();
if(this.applicationIsRunning) {
throw new AssertionError("This Flutter engine instance is already running an application");
} else {
this.mFlutterJNI.runBundleAndSnapshotFromLibrary(bundlePaths, entrypoint, libraryPath, this.mContext.getResources().getAssets());
this.applicationIsRunning = true;
}
}
最后还是调用FlutterJNI.runBundleAndSnapshotFromLibrary()
,并设置启动标志为true。
FlutterJNI.class
@UiThread
public void runBundleAndSnapshotFromLibrary(@NonNull String[] prioritizedBundlePaths, @Nullable String entrypointFunctionName, @Nullable String pathToEntrypointFunction, @NonNull AssetManager assetManager) {
this.ensureAttachedToNative();
this.nativeRunBundleAndSnapshotFromLibrary(this.nativePlatformViewId.longValue(), prioritizedBundlePaths, entrypointFunctionName, pathToEntrypointFunction, assetManager);
}
private native void nativeRunBundleAndSnapshotFromLibrary(long var1, @NonNull String[] var3, @Nullable String var4, @Nullable String var5, @NonNull AssetManager var6);
platform_view_android_jni.cc
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jobjectArray jbundlepaths,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager) {
auto asset_manager = std::make_shared<blink::AssetManager>();
for (const auto& bundlepath :
fml::jni::StringArrayToVector(env, jbundlepaths)) {
if (bundlepath.empty()) {
continue;
}
// If we got a bundle path, attempt to use that as a directory asset
// bundle or a zip asset bundle.
const auto file_ext_index = bundlepath.rfind(".");
if (bundlepath.substr(file_ext_index) == ".zip") {
asset_manager->PushBack(std::make_unique<blink::ZipAssetStore>(
bundlepath, "assets/flutter_assets"));
} else {
asset_manager->PushBack(
std::make_unique<blink::DirectoryAssetBundle>(fml::OpenDirectory(
bundlepath.c_str(), false, fml::FilePermission::kRead)));
// Use the last path component of the bundle path to determine the
// directory in the APK assets.
const auto last_slash_index = bundlepath.rfind("/", bundlepath.size());
if (last_slash_index != std::string::npos) {
auto apk_asset_dir = bundlepath.substr(
last_slash_index + 1, bundlepath.size() - last_slash_index);
asset_manager->PushBack(std::make_unique<blink::APKAssetProvider>(
env, // jni environment
jAssetManager, // asset manager
std::move(apk_asset_dir)) // apk asset dir
);
}
}
}
auto isolate_configuration = CreateIsolateConfiguration(*asset_manager);
if (!isolate_configuration) {
FML_DLOG(ERROR)
<< "Isolate configuration could not be determined for engine launch.";
return;
}
RunConfiguration config(std::move(isolate_configuration),
std::move(asset_manager));
{
auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
if ((entrypoint.size() > 0) && (libraryUrl.size() > 0)) {
config.SetEntrypointAndLibrary(std::move(entrypoint),
std::move(libraryUrl));
} else if (entrypoint.size() > 0) {
config.SetEntrypoint(std::move(entrypoint));
}
}
ANDROID_SHELL_HOLDER->Launch(std::move(config));
}
可见最后走到C++层的Launch()
,后面开始启动的逻辑,这里不再展开了。
总结
- 在FlutterApplication中调用
FlutterMain.startInitialization()
开始初始化,初始化一些配置和加载so库,在C++层动态注册供Java使用的方法,同时也获取Java的类和方法。 - FlutterActivity创建FlutterActivityDelegate用与处理所有逻辑。
- FlutterNativeView创建FlutterJNI进行attach C++层、创建插件注册者进行插件消息的管理等。
- FlutterView创建FlutterNativeView、创建PlatformPlugin管理平台插件等。
-
FlutterActivityDelegate.onCreate()
中进行C++层的init、创建FlutterView、setContentView()
、最后调用runBundle()
开始启动App。