接著上篇分析生均,這篇從FlutterActivity創(chuàng)建開始切入誉帅。
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
首先可以看出观蓄,默認(rèn)創(chuàng)建的MainActivity 沒有我們常見的setContentView()
秧荆,那應(yīng)該是在FlutterActivity里面設(shè)置的谭企。
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()
廓译,并且創(chuàng)建FlutterView
也是為null评肆,那么核心邏輯應(yīng)該在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);
}
}
}
- 有個(gè)關(guān)鍵的方法
FlutterMain.ensureInitializationComplete()
非区,下面分析瓜挽。 - 接著看創(chuàng)建FlutterView。
this.viewFactory.createFlutterNativeView()
最終來到FlutterActivity.createFlutterNativeView()
征绸,結(jié)果返回的為null久橙,所以FlutterNativeView的創(chuàng)建是在FlutterView中,下面分析管怠。 - 創(chuàng)建了flutterView后淆衷,用了
setContentView(this.flutterView)
,所以整個(gè)activity的布局就是一個(gè)surfaceView - 運(yùn)行的方法
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);
}
}
}
方法作用在創(chuàng)建FlutterView之前先確保FlutterMain初始化完成,就是FlutterMain.startInitialization()
要完成她肯,關(guān)于此方法分析見上文佳头。
關(guān)鍵的檢查方法是sResourceExtractor.waitForCompletion();
,在資源初始化完成后進(jìn)行nativeInit
晴氨,此時(shí)調(diào)用了C++層的方法init
康嘉,開始初始化。
FlutterView
接著if(this.flutterView == null) 的判斷籽前,這里需要?jiǎng)?chuàng)建FlutterView亭珍。
FlutterView不是直接繼承View,而是SurfaceView枝哄,相關(guān)知識(shí)可以自行搜索肄梨。
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()
比較關(guān)鍵的有
- 創(chuàng)建FlutterNativeView
- 初始化
DartExecutor
,JNI的創(chuàng)建在下面FlutterNativeView提到膘格。 - 設(shè)置surfaceView的回調(diào),通過FlutterJNI使得與Java層和dart層的狀態(tài)同步财松。
- 創(chuàng)建系統(tǒng)的native插件瘪贱,關(guān)于插件的分析會(huì)另起一文。
FlutterNativeView
FlutterNativeView不是View辆毡,它是與C++層進(jìn)行消息傳遞的媒介菜秦,實(shí)現(xiàn)了BinaryMessenger
,二進(jìn)制消息傳遞方法舶掖。
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);
}
}
由類源碼可知球昨,定義消息發(fā)送、處理消息眨攘、設(shè)置消息處理器主慰、響應(yīng)消息的接口或者方法嚣州。在FlutterNativeView實(shí)現(xiàn)。
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();
}
可知
- 創(chuàng)建了插件的注冊(cè)者
- 創(chuàng)建了
FlutterJNI
用于與C++層進(jìn)行交互 - 關(guān)鍵方法
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);
最終會(huì)調(diào)用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成功后會(huì)返回nativePlatformViewId
共螺,用于標(biāo)志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層初始化核心邏輯大致說完匀哄,還剩下一個(gè)運(yùn)行的方法。
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;
}
}
最后還是調(diào)用FlutterJNI.runBundleAndSnapshotFromLibrary()
雏蛮,并設(shè)置啟動(dòng)標(biāo)志為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()
,后面開始啟動(dòng)的邏輯挑秉,這里不再展開了法梯。
總結(jié)
- 在FlutterApplication中調(diào)用
FlutterMain.startInitialization()
開始初始化,初始化一些配置和加載so庫衷模,在C++層動(dòng)態(tài)注冊(cè)供Java使用的方法鹊汛,同時(shí)也獲取Java的類和方法。 - FlutterActivity創(chuàng)建FlutterActivityDelegate用與處理所有邏輯阱冶。
- FlutterNativeView創(chuàng)建FlutterJNI進(jìn)行attach C++層刁憋、創(chuàng)建插件注冊(cè)者進(jìn)行插件消息的管理等。
- FlutterView創(chuàng)建FlutterNativeView木蹬、創(chuàng)建PlatformPlugin管理平臺(tái)插件等至耻。
-
FlutterActivityDelegate.onCreate()
中進(jìn)行C++層的init、創(chuàng)建FlutterView镊叁、setContentView()
尘颓、最后調(diào)用runBundle()
開始啟動(dòng)App。