【Flutter】混合开发之Flutter预加载解决第一次加载页面缓慢问题

NativeFlutter混合开发,通过FlutterFragment加载Flutter页面,但Flutter页面第一次加载时非常缓慢,可以通过Flutter预加载的方式来减少第一次加载的耗时。

预备知识

  1. 一个Native进程只有一个DartVM
  2. 第一个FlutterEngine初始化时,会创建并初始化DartVM
  3. 一个DartVM可以有多个FlutterEngine,每个FlutterEngine都运行在自己的Isolate中,他们的内存数据不共享,需要通过Isolate事先设置的port(顶级函数)通讯。

实现方式Flutter页面第一次调用时,会初始化Flutter相关的东西,比如FlutterEngineDartVM等等,所以可以提前初始化Flutter相关的东西来达到减少第一次启动的耗时:

  • 提前预加载
  • 全局使用同一个FlutterEngine

App 每个进程中创建第一个 FlutterEngine 实例的时候会加载 Flutter 引擎的原生库并启动 Dart VM(VM 存活生命周期跟随进程),随后同进程中其他的 FlutterEngine 将在同一个 VM 实例上运行,而第一次启动耗时主要花费在加载 Flutter 引擎的原生库和启动 Dart VM。所以可以提前初始化一个FlutterEngine来减少第一次加载时的耗时。

1. 提前预加载

1.1 FlutterHelper

FlutterHelper主要用于预加载FlutterEngine,初始化FlutterEngine,获取FlutterEngine。预加载时,它会在Handler空闲时对FlutterEngine初始化。

/**
 * Created by : yds
 * Time: 2022-07-27 10:02
 */

import android.content.Context;
import android.os.Looper;
import android.os.MessageQueue;

import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.loader.FlutterLoader;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class FlutterHelper {
    
    

    private FlutterHelper() {
    
    
    }

    //FlutterEngine缓存的key
    public static final String FLUTTER_ENGINE = "flutter_engine";

    //flutter初始化成功的消息
    public static final String FLUTTER_ENGINE_INIT_FINISH = "flutter_engine_init_finish";

    private static volatile FlutterHelper instance;

    public static FlutterHelper getInstance() {
    
    
        if (instance == null) {
    
    
            synchronized (FlutterHelper.class) {
    
    
                if (instance == null) {
    
    
                    instance = new FlutterHelper();
                }
            }
        }
        return instance;
    }

    public void preloadFlutterEngine(Context context) {
    
    
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
    
    
            @Override
            public boolean queueIdle() {
    
    
                initFlutterEngine(context);
                return true;
            }
        });
    }

    public synchronized FlutterEngine initFlutterEngine(Context context){
    
    
        if (!FlutterEngineCache.getInstance().contains(FLUTTER_ENGINE)) {
    
    
        //这里建议用FlutterEngineGroup来创建FlutterEngine
            FlutterEngine engine = new FlutterEngine(context.getApplicationContext());
            System.out.println("flutterEngine:"+engine);
            GeneratedPluginRegistrant.registerWith(engine);
            //Channel 注册要紧跟引擎初始化之后,否则会有在dart中调用 Channel 因为还未初始化完成而导致的时序问题
            //FlutterBridge用于将Channel封装,统一提供服务
            FlutterBridge.init(engine);
            engine.getDartExecutor().executeDartEntrypoint(DartExecutor.DartEntrypoint.createDefault());
            FlutterEngineCache.getInstance().put(FLUTTER_ENGINE, engine);
            return engine;
        } else {
    
    
            return getFlutterEngine();
        }
    }

    public FlutterEngine getFlutterEngine(){
    
    
        if (isInitFinish()) {
    
    
            return FlutterEngineCache.getInstance().get(FLUTTER_ENGINE);
        } else {
    
    
            try {
    
    
                throw new Exception("请先初始化 FlutterEngine!");
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
        return null;
    }

    public boolean isInitFinish() {
    
    
        return FlutterEngineCache.getInstance().get(FLUTTER_ENGINE) != null;
    }

}

1.2 FlutterBridge

FlutterBridge主要用于管理与Flutter通信的Channel

/**
 * Created by : yds
 * Time: 2022-07-27 10:13
 */

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMessageCodec;

public class FlutterBridge implements  MethodChannel.MethodCallHandler, BasicMessageChannel.MessageHandler<Object> {
    
    

    private static final String FLUTTER_MESSAGE_CHANNEL = "message_channel";
    private static final String FLUTTER_SEARCH_DATA_CHANNEL = "searchflutterfragment/searchscandata";

    private static volatile FlutterBridge instance;

    private static List<MethodChannel> mMethodChannels = new ArrayList<>();

    public static BasicMessageChannel<Object> mChannel;

    private FlutterBridge() {
    
    
    }

    public static FlutterBridge getInstance() {
    
    
        if (instance == null) {
    
    
            synchronized (FlutterBridge.class) {
    
    
                if (instance == null) {
    
    
                    instance = new FlutterBridge();
                }
            }
        }
        return instance;
    }


    public static FlutterBridge init(FlutterEngine flutterEngine) {
    
    
        MethodChannel channel = new MethodChannel(flutterEngine.getDartExecutor(), FLUTTER_MESSAGE_CHANNEL);
        channel.setMethodCallHandler(getInstance());
        mChannel = new BasicMessageChannel<>(
                flutterEngine.getDartExecutor().getBinaryMessenger(), FLUTTER_SEARCH_DATA_CHANNEL,
                StandardMessageCodec.INSTANCE
        );
        mChannel.setMessageHandler(getInstance());
        mMethodChannels.add(channel);
        return getInstance();
    }

    public static <T> void  send(@Nullable T message,@Nullable final BasicMessageChannel.Reply<Object> callback){
    
    
        mChannel.send(message,callback);
    }

    /**
     * MethodChannel回调
     * <p>
     * 用于接收从flutter向native发送消息
     *
     * @param call
     * @param result
     */
    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
    
    

    }

    /**
     * BasicMessageChannel回调
     * <p>
     * 用于接收从flutter向native发送消息
     *
     * @param message
     * @param reply
     */
    @Override
    public void onMessage(@Nullable Object message, @NonNull BasicMessageChannel.Reply reply) {
    
    

    }
}

1.3 使用

  • 首先在Application中进行预加载
public class MyApplication extends Application {
    
    
	public void onCreate() {
    
    
		super.onCreate();
		FlutterHelper.getInstance().preloadFlutterEngine(this);
	}
}

2. 全局使用同一个FlutterEngine

  • FlutterHelper预加载时会创建一个FlutterEngine,然后会将FlutterEngine存储在FlutterEngineCache中。
  • FlutterFragment通过withCachedEngine获取FlutterHelper创建的FlutterEngine,并通过build方法创建FlutterFragment
public class SearchFragment extends Fragment  implements OnScanDataListener {
    
    

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        initFlutterEngine();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    
    
        return inflater.inflate(R.layout.search_fragment_layout,container,false);
    }

    private void initFlutterEngine(){
    
    
        FlutterFragment flutterFragment = FlutterFragment.withCachedEngine(FlutterHelper.FLUTTER_ENGINE).build();
        getChildFragmentManager().beginTransaction().replace(R.id.container,flutterFragment).commit();
    }


    @Override
    public void onScanData(String data) {
    
    
        FlutterBridge.send(data,new BasicMessageChannel.Reply<Object>() {
    
    
            @Override
            public void reply(@Nullable Object reply) {
    
    
                if (reply != null) {
    
    
                    long endTime = System.currentTimeMillis();
                    System.out.println("endTime:" + endTime);
                    System.out.println("onScanData:" + reply.toString());
                }
            }
        });
    }
}

猜你喜欢

转载自blog.csdn.net/u013293125/article/details/126019202