Commit 908b83ec authored by yangwu.jia's avatar yangwu.jia

Merge branch 'feature/flutter_1.9_upgrade' into feature/flutter_1.9_androidx_upgrade

# Conflicts:
#	android/src/main/java/com/idlefish/flutterboost/FlutterBoostPlugin.java
parents dc9713d1 3d998dc4
...@@ -91,9 +91,10 @@ public class ContainerRecord implements IContainerRecord { ...@@ -91,9 +91,10 @@ public class ContainerRecord implements IContainerRecord {
mManager.pushRecord(this); mManager.pushRecord(this);
mProxy.appear();
mContainer.getBoostFlutterView().onAttach(); mContainer.getBoostFlutterView().onAttach();
mProxy.appear();
} }
@Override @Override
......
package com.idlefish.flutterboost; package com.idlefish.flutterboost;
import android.os.Handler;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.idlefish.flutterboost.interfaces.IContainerRecord; import com.idlefish.flutterboost.interfaces.IContainerRecord;
import java.io.Serializable; import java.io.Serializable;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
...@@ -217,6 +215,9 @@ public class FlutterBoostPlugin { ...@@ -217,6 +215,9 @@ public class FlutterBoostPlugin {
} }
result.success(pageInfo); result.success(pageInfo);
NewFlutterBoost.instance().setFlutterPostFrameCallTime(new Date().getTime());
} catch (Throwable t) { } catch (Throwable t) {
result.error("no flutter page found!", t.getMessage(), t); result.error("no flutter page found!", t.getMessage(), t);
} }
......
...@@ -135,8 +135,10 @@ public class FlutterViewContainerManager implements IContainerManager { ...@@ -135,8 +135,10 @@ public class FlutterViewContainerManager implements IContainerManager {
final String uniqueId = ContainerRecord.genUniqueId(url); final String uniqueId = ContainerRecord.genUniqueId(url);
urlParams.put(IContainerRecord.UNIQ_KEY,uniqueId); urlParams.put(IContainerRecord.UNIQ_KEY,uniqueId);
IContainerRecord currentTopRecord = getCurrentTopRecord();
if(onResult != null) { if(onResult != null) {
mOnResults.put(uniqueId,onResult); mOnResults.put(currentTopRecord.uniqueId(),onResult);
} }
NewFlutterBoost.instance().platform().openContainer(context,url,urlParams,requestCode,exts); NewFlutterBoost.instance().platform().openContainer(context,url,urlParams,requestCode,exts);
......
...@@ -31,6 +31,15 @@ public class NewFlutterBoost { ...@@ -31,6 +31,15 @@ public class NewFlutterBoost {
private PluginRegistry mRegistry; private PluginRegistry mRegistry;
static NewFlutterBoost sInstance = null; static NewFlutterBoost sInstance = null;
private long FlutterPostFrameCallTime=0;
public long getFlutterPostFrameCallTime(){
return FlutterPostFrameCallTime;
}
public void setFlutterPostFrameCallTime(long FlutterPostFrameCallTime){
this.FlutterPostFrameCallTime=FlutterPostFrameCallTime;
}
public static NewFlutterBoost instance() { public static NewFlutterBoost instance() {
if (sInstance == null) { if (sInstance == null) {
sInstance = new NewFlutterBoost(); sInstance = new NewFlutterBoost();
......
package com.idlefish.flutterboost;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.TextureView;
import io.flutter.Log;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class XFlutterTextureView extends TextureView implements FlutterRenderer.RenderSurface {
private static final String TAG = "XFlutterTextureView";
private boolean isSurfaceAvailableForRendering;
private boolean isAttachedToFlutterRenderer;
@Nullable
private FlutterRenderer flutterRenderer;
@NonNull
private Set<OnFirstFrameRenderedListener> onFirstFrameRenderedListeners;
private final SurfaceTextureListener surfaceTextureListener;
public XFlutterTextureView(@NonNull Context context) {
this(context, (AttributeSet)null);
}
public XFlutterTextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
this.isSurfaceAvailableForRendering = false;
this.isAttachedToFlutterRenderer = false;
this.onFirstFrameRenderedListeners = new HashSet();
this.surfaceTextureListener = new SurfaceTextureListener() {
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
Log.v("FlutterTextureView", "SurfaceTextureListener.onSurfaceTextureAvailable()");
XFlutterTextureView.this.isSurfaceAvailableForRendering = true;
if (XFlutterTextureView.this.isAttachedToFlutterRenderer) {
XFlutterTextureView.this.connectSurfaceToRenderer();
}
}
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {
Log.v("FlutterTextureView", "SurfaceTextureListener.onSurfaceTextureSizeChanged()");
if (XFlutterTextureView.this.isAttachedToFlutterRenderer) {
XFlutterTextureView.this.changeSurfaceSize(width, height);
}
}
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {
}
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
Log.v("FlutterTextureView", "SurfaceTextureListener.onSurfaceTextureDestroyed()");
XFlutterTextureView.this.isSurfaceAvailableForRendering = false;
if (XFlutterTextureView.this.isAttachedToFlutterRenderer) {
XFlutterTextureView.this.disconnectSurfaceFromRenderer();
}
return true;
}
};
this.init();
}
private void init() {
this.setSurfaceTextureListener(this.surfaceTextureListener);
}
public void attachToRenderer(@NonNull FlutterRenderer flutterRenderer) {
Log.v("FlutterTextureView", "Attaching to FlutterRenderer.");
if (this.flutterRenderer != null) {
Log.v("FlutterTextureView", "Already connected to a FlutterRenderer. Detaching from old one and attaching to new one.");
this.flutterRenderer.detachFromRenderSurface();
}
this.flutterRenderer = flutterRenderer;
this.isAttachedToFlutterRenderer = true;
if (this.isSurfaceAvailableForRendering) {
Log.v("FlutterTextureView", "Surface is available for rendering. Connecting FlutterRenderer to Android surface.");
this.connectSurfaceToRenderer();
}
}
public void detachFromRenderer() {
if (this.flutterRenderer != null) {
if (this.getWindowToken() != null) {
Log.v("FlutterTextureView", "Disconnecting FlutterRenderer from Android surface.");
this.disconnectSurfaceFromRenderer();
}
this.flutterRenderer = null;
this.isAttachedToFlutterRenderer = false;
} else {
Log.w("FlutterTextureView", "detachFromRenderer() invoked when no FlutterRenderer was attached.");
}
}
private void connectSurfaceToRenderer() {
if (this.flutterRenderer != null && this.getSurfaceTexture() != null) {
Surface surface= new Surface(this.getSurfaceTexture());
this.flutterRenderer.surfaceCreated(surface);
surface.release();
} else {
throw new IllegalStateException("connectSurfaceToRenderer() should only be called when flutterRenderer and getSurfaceTexture() are non-null.");
}
}
private void changeSurfaceSize(int width, int height) {
if (this.flutterRenderer == null) {
throw new IllegalStateException("changeSurfaceSize() should only be called when flutterRenderer is non-null.");
} else {
Log.v("FlutterTextureView", "Notifying FlutterRenderer that Android surface size has changed to " + width + " x " + height);
this.flutterRenderer.surfaceChanged(width, height);
}
}
private void disconnectSurfaceFromRenderer() {
if (this.flutterRenderer == null) {
throw new IllegalStateException("disconnectSurfaceFromRenderer() should only be called when flutterRenderer is non-null.");
} else {
this.flutterRenderer.surfaceDestroyed();
}
}
public void addOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) {
this.onFirstFrameRenderedListeners.add(listener);
}
public void removeOnFirstFrameRenderedListener(@NonNull OnFirstFrameRenderedListener listener) {
this.onFirstFrameRenderedListeners.remove(listener);
}
public void onFirstFrameRendered() {
Log.v("FlutterTextureView", "onFirstFrameRendered()");
Iterator var1 = this.onFirstFrameRenderedListeners.iterator();
while(var1.hasNext()) {
OnFirstFrameRenderedListener listener = (OnFirstFrameRenderedListener)var1.next();
listener.onFirstFrameRendered();
}
}
}
\ No newline at end of file
...@@ -202,7 +202,7 @@ public class XFlutterView extends FrameLayout { ...@@ -202,7 +202,7 @@ public class XFlutterView extends FrameLayout {
break; break;
case texture: case texture:
Log.v(TAG, "Internally using a FlutterTextureView."); Log.v(TAG, "Internally using a FlutterTextureView.");
FlutterTextureView flutterTextureView = new FlutterTextureView(getContext()); XFlutterTextureView flutterTextureView = new XFlutterTextureView(getContext());
renderSurface = flutterTextureView; renderSurface = flutterTextureView;
addView(flutterTextureView); addView(flutterTextureView);
break; break;
...@@ -585,7 +585,6 @@ public class XFlutterView extends FrameLayout { ...@@ -585,7 +585,6 @@ public class XFlutterView extends FrameLayout {
+ " to new engine."); + " to new engine.");
detachFromFlutterEngine(); detachFromFlutterEngine();
} }
this.requestFocus();
this.flutterEngine = flutterEngine; this.flutterEngine = flutterEngine;
// Instruct our FlutterRenderer that we are now its designated RenderSurface. // Instruct our FlutterRenderer that we are now its designated RenderSurface.
...@@ -693,7 +692,6 @@ public class XFlutterView extends FrameLayout { ...@@ -693,7 +692,6 @@ public class XFlutterView extends FrameLayout {
// signifies that this View does not process input (until a new engine is attached). // signifies that this View does not process input (until a new engine is attached).
// TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
// resolveMemoryLeaks();
// Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface. // Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface.
FlutterRenderer flutterRenderer = flutterEngine.getRenderer(); FlutterRenderer flutterRenderer = flutterEngine.getRenderer();
// didRenderFirstFrame = false; // didRenderFirstFrame = false;
...@@ -702,32 +700,12 @@ public class XFlutterView extends FrameLayout { ...@@ -702,32 +700,12 @@ public class XFlutterView extends FrameLayout {
flutterEngine = null; flutterEngine = null;
} }
public void release(){ public void release(){
textInputPlugin.release(); if(textInputPlugin!=null){
} textInputPlugin.release();
public void resolveMemoryLeaks(){
try {
Class clazz = TextInputPlugin.class;
for (Field f : clazz.getDeclaredFields()) {
System.out.println(f.isAccessible());
f.setAccessible(true);
if(f.get(this.textInputPlugin) instanceof TextInputChannel){
System.out.println( "xxxxxx:" +f.getName());
TextInputChannel channel=(TextInputChannel)f.get(this.textInputPlugin);
channel.setTextInputMethodHandler(null);
}
}
} catch (Throwable e) {
e.printStackTrace();
} }
} }
/** /**
* Returns true if this {@code FlutterView} is currently attached to a {@link FlutterEngine}. * Returns true if this {@code FlutterView} is currently attached to a {@link FlutterEngine}.
*/ */
......
...@@ -5,6 +5,7 @@ import android.app.Activity; ...@@ -5,6 +5,7 @@ import android.app.Activity;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
...@@ -102,6 +103,8 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine ...@@ -102,6 +103,8 @@ public class FlutterActivityAndFragmentDelegate implements IFlutterViewContaine
host.configureFlutterEngine(flutterEngine); host.configureFlutterEngine(flutterEngine);
host.getActivity().getWindow().setFormat(PixelFormat.TRANSLUCENT);
} }
......
...@@ -3,6 +3,7 @@ package com.idlefish.flutterboost.containers; ...@@ -3,6 +3,7 @@ package com.idlefish.flutterboost.containers;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
...@@ -18,6 +19,8 @@ import io.flutter.embedding.android.SplashScreen; ...@@ -18,6 +19,8 @@ import io.flutter.embedding.android.SplashScreen;
import io.flutter.embedding.engine.FlutterEngine; import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener; import io.flutter.embedding.engine.renderer.OnFirstFrameRenderedListener;
import java.util.Date;
/** /**
* {@code View} that displays a {@link SplashScreen} until a given {@link FlutterView} * {@code View} that displays a {@link SplashScreen} until a given {@link FlutterView}
* renders its first frame. * renders its first frame.
...@@ -39,7 +42,7 @@ public class FlutterSplashView extends FrameLayout { ...@@ -39,7 +42,7 @@ public class FlutterSplashView extends FrameLayout {
@Nullable @Nullable
private String previousCompletedSplashIsolate; private String previousCompletedSplashIsolate;
private boolean hasRendered=false; private Handler handler = new Handler();
@NonNull @NonNull
private final FlutterView.FlutterEngineAttachmentListener flutterEngineAttachmentListener = new FlutterView.FlutterEngineAttachmentListener() { private final FlutterView.FlutterEngineAttachmentListener flutterEngineAttachmentListener = new FlutterView.FlutterEngineAttachmentListener() {
...@@ -57,11 +60,40 @@ public class FlutterSplashView extends FrameLayout { ...@@ -57,11 +60,40 @@ public class FlutterSplashView extends FrameLayout {
@NonNull @NonNull
private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() { private final OnFirstFrameRenderedListener onFirstFrameRenderedListener = new OnFirstFrameRenderedListener() {
int i=0;
@Override @Override
public void onFirstFrameRendered() { public void onFirstFrameRendered() {
if (splashScreen != null) {
transitionToFlutter(); if(NewFlutterBoost.instance().platform().whenEngineStart()== NewFlutterBoost.ConfigBuilder.FLUTTER_ACTIVITY_CREATED){
long now=new Date().getTime();
long flutterPostFrameCallTime=NewFlutterBoost.instance().getFlutterPostFrameCallTime();
if(flutterPostFrameCallTime!=0&& (now-flutterPostFrameCallTime)>800){
if (splashScreen != null) {
transitionToFlutter();
}
return;
}
handler.postDelayed(new Runnable() {
@Override
public void run() {
onFirstFrameRenderedListener.onFirstFrameRendered();
}
}, 200);
}else{
if (splashScreen != null) {
transitionToFlutter();
}
} }
} }
}; };
...@@ -91,24 +123,6 @@ public class FlutterSplashView extends FrameLayout { ...@@ -91,24 +123,6 @@ public class FlutterSplashView extends FrameLayout {
} }
} }
@Nullable
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.previousCompletedSplashIsolate = previousCompletedSplashIsolate;
savedState.splashScreenState = splashScreen != null ? splashScreen.saveSplashScreenState() : null;
return savedState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
previousCompletedSplashIsolate = savedState.previousCompletedSplashIsolate;
splashScreenState = savedState.splashScreenState;
}
/** /**
* Displays the given {@code splashScreen} on top of the given {@code flutterView} until * Displays the given {@code splashScreen} on top of the given {@code flutterView} until
* Flutter has rendered its first frame, then the {@code splashScreen} is transitioned away. * Flutter has rendered its first frame, then the {@code splashScreen} is transitioned away.
...@@ -259,17 +273,14 @@ public class FlutterSplashView extends FrameLayout { ...@@ -259,17 +273,14 @@ public class FlutterSplashView extends FrameLayout {
public static class SavedState extends BaseSavedState { public static class SavedState extends BaseSavedState {
public static Creator CREATOR = new Creator() { public static Creator CREATOR = new Creator() {
@Override public FlutterSplashView.SavedState createFromParcel(Parcel source) {
public SavedState createFromParcel(Parcel source) { return new FlutterSplashView.SavedState(source);
return new SavedState(source);
} }
@Override public FlutterSplashView.SavedState[] newArray(int size) {
public SavedState[] newArray(int size) { return new FlutterSplashView.SavedState[size];
return new SavedState[size];
} }
}; };
private String previousCompletedSplashIsolate; private String previousCompletedSplashIsolate;
private Bundle splashScreenState; private Bundle splashScreenState;
...@@ -279,20 +290,23 @@ public class FlutterSplashView extends FrameLayout { ...@@ -279,20 +290,23 @@ public class FlutterSplashView extends FrameLayout {
SavedState(Parcel source) { SavedState(Parcel source) {
super(source); super(source);
previousCompletedSplashIsolate = source.readString(); this.previousCompletedSplashIsolate = source.readString();
splashScreenState = source.readBundle(getClass().getClassLoader()); this.splashScreenState = source.readBundle(this.getClass().getClassLoader());
} }
@Override
public void writeToParcel(Parcel out, int flags) { public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags); super.writeToParcel(out, flags);
out.writeString(previousCompletedSplashIsolate); out.writeString(this.previousCompletedSplashIsolate);
out.writeBundle(splashScreenState); out.writeBundle(this.splashScreenState);
} }
} }
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
handler.removeCallbacksAndMessages(null);
}
public void onAttach() { public void onAttach() {
Debuger.log("BoostFlutterView onAttach"); Debuger.log("BoostFlutterView onAttach");
......
...@@ -228,7 +228,7 @@ public class NewBoostFlutterActivity extends Activity ...@@ -228,7 +228,7 @@ public class NewBoostFlutterActivity extends Activity
} }
@NonNull @NonNull
private View createFlutterView() { protected View createFlutterView() {
return delegate.onCreateView( return delegate.onCreateView(
null /* inflater */, null /* inflater */,
null /* container */, null /* container */,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'container/boost_container.dart'; import 'container/boost_container.dart';
...@@ -60,6 +61,26 @@ class FlutterBoost { ...@@ -60,6 +61,26 @@ class FlutterBoost {
PrePushRoute prePush, PrePushRoute prePush,
PostPushRoute postPush}) { PostPushRoute postPush}) {
if(Platform.isAndroid){
WidgetsBinding.instance.addPostFrameCallback((_){
singleton.channel.invokeMethod<Map>('pageOnStart').then((Map pageInfo){
if (pageInfo == null || pageInfo.isEmpty) return;
if (pageInfo.containsKey("name") &&
pageInfo.containsKey("params") &&
pageInfo.containsKey("uniqueId")) {
ContainerCoordinator.singleton.nativeContainerDidShow(
pageInfo["name"], pageInfo["params"], pageInfo["uniqueId"]);
}
});
});
}
return (BuildContext context, Widget child) { return (BuildContext context, Widget child) {
assert(child is Navigator, 'child must be Navigator, what is wrong?'); assert(child is Navigator, 'child must be Navigator, what is wrong?');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment