[Android] support preinit && predonload mode (#2491)

# feature : 
1. supprot preDownLoad bundle
2. support preInitInstanceContext

# performance : 
1. 200ms improve 

# usage: 
add url  params 
- ` ?preDownLoad=true`
- or `?preInitInstance=vue/rax`
- or both of them `?preDownLoad=true&preInitInstance=vue/rax`

# sample: 
- case: `http://editor.weex.io/compiled/8afdb78575e9cbbdf35d32d102843885/bundle.weex.js?preInitInstance=vue&preDownLoad=true`
- originurl: `http://editor.weex.io/compiled/8afdb78575e9cbbdf35d32d102843885/bundle.weex.js`

diff --git a/src/main/java/com/alibaba/weex/WXPageActivity.java b/src/main/java/com/alibaba/weex/WXPageActivity.java
index 606b5d1..2deec2e 100644
--- a/src/main/java/com/alibaba/weex/WXPageActivity.java
+++ b/src/main/java/com/alibaba/weex/WXPageActivity.java
@@ -150,6 +150,10 @@
 
     mWxAnalyzerDelegate = new WXAnalyzerDelegate(this);
     mWxAnalyzerDelegate.onCreate();
+
+    //if (mInstance.isPreDownLoad() || mInstance.isPreInitMode()){
+      mInstance.onInstanceReady();
+    //}
   }
 
   @Override
@@ -219,6 +223,9 @@
   }
 
   private void loadWXfromService(final String url) {
+
+    Log.d("test->", "on ActivityCreate ,loadWXfromService: ");
+
     mProgressBar.setVisibility(View.VISIBLE);
 
     if (mInstance != null) {
@@ -226,7 +233,14 @@
     }
 
     RenderContainer renderContainer = new RenderContainer(this);
-    mInstance = new WXSDKInstance(this);
+    //mInstance = new WXSDKInstance(this);
+    mInstance = WXPreLoadManager.getInstance().offerPreInitInstance(url);
+    if (null != mInstance){
+      mInstance.init(this);
+    }else {
+      mInstance = new WXSDKInstance(this);
+    }
+
     mInstance.setRenderContainer(renderContainer);
     mInstance.registerRenderListener(this);
     mInstance.setNestedInstanceInterceptor(this);
@@ -234,6 +248,11 @@
     mInstance.setTrackComponent(true);
     mContainer.addView(renderContainer);
 
+    if (mInstance.isPreDownLoad()){
+      return;
+    }
+
+
     WXHttpTask httpTask = new WXHttpTask();
     httpTask.url = url;
     httpTask.requestListener = new WXRequestListener() {
diff --git a/src/main/java/com/alibaba/weex/WXPreLoadManager.java b/src/main/java/com/alibaba/weex/WXPreLoadManager.java
new file mode 100644
index 0000000..9b45b27
--- /dev/null
+++ b/src/main/java/com/alibaba/weex/WXPreLoadManager.java
@@ -0,0 +1,93 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.alibaba.weex;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import android.util.Log;
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.common.WXRenderStrategy;
+import com.taobao.weex.utils.WXLogUtils;
+
+/**
+ * @author zhongcang
+ * @date 2019/5/13
+ */
+public class WXPreLoadManager {
+
+    private Map<String, WXSDKInstance> mPreInitInstanceMap;
+
+    private static class SingleTonHolder {
+        private static final WXPreLoadManager INSTANCE = new WXPreLoadManager();
+    }
+
+    private WXPreLoadManager() {
+        mPreInitInstanceMap = new ConcurrentHashMap<>();
+    }
+
+    public static WXPreLoadManager getInstance() {
+        return SingleTonHolder.INSTANCE;
+    }
+
+    public WXSDKInstance offerPreInitInstance(String pageName) {
+        WXSDKInstance instance = mPreInitInstanceMap.remove(pageName);
+        return instance;
+    }
+
+    public void preLoad(String url) {
+
+        boolean preDownLoad = url.contains("preDownLoad=true");
+        boolean preInit = url.contains("preInitInstance=rax") || url.contains("preInitInstance=vue");
+        if (!preDownLoad && !preInit){
+            return;
+        }
+
+
+        WXSDKInstance instance = new WXSDKInstance();
+        Map<String, Object> options = new HashMap<>();
+        options.put("bundleUrl", url);
+        options.put("render_strategy", WXRenderStrategy.APPEND_ASYNC.toString());
+        options.put("wxPreInit",preInit);
+        options.put("wxPreDownLoad",preDownLoad);
+        String script = null;
+        if (preInit){
+            if (url.contains("preInitInstance=rax")) {
+                script = "// { \"framework\": \"Rax\" }\n";
+            } else if (url.contains("preInitInstance=vue")) {
+                script = "// { \"framework\": \"Vue\" }\n";
+            } else {
+                WXLogUtils.e("WXPreLoadManager", "unsupport init bundle type :" + url);
+            }
+            if (null != script) {
+                mPreInitInstanceMap.put(url, instance);
+                Log.d("test->", "start preInit: ");
+                instance.preInit(url, script, options, null, WXRenderStrategy.APPEND_ASYNC);
+            }
+        }
+        if (preDownLoad){
+            if (!mPreInitInstanceMap.containsKey(url)) {
+                mPreInitInstanceMap.put(url, instance);
+            }
+            Log.d("test->", "start preDownLoad: ");
+            instance.preDownLoad(url, options, null, WXRenderStrategy.APPEND_ASYNC);
+        }
+    }
+}
diff --git a/src/main/java_zxing/com/google/zxing/client/android/CaptureActivity.java b/src/main/java_zxing/com/google/zxing/client/android/CaptureActivity.java
index 6cf57f2..1170348 100755
--- a/src/main/java_zxing/com/google/zxing/client/android/CaptureActivity.java
+++ b/src/main/java_zxing/com/google/zxing/client/android/CaptureActivity.java
@@ -47,6 +47,9 @@
 
 import com.alibaba.weex.R;
 import com.alibaba.weex.WXPageActivity;
+import com.alibaba.weex.WXPreLoadManager;
+import com.alibaba.weex.constants.Constants;
+
 import com.google.zxing.BarcodeFormat;
 import com.google.zxing.DecodeHintType;
 import com.google.zxing.Result;
@@ -587,6 +590,13 @@
 				finish();
 				return;
 			} else {
+				String urlData = uri.getQueryParameter(Constants.WEEX_TPL_KEY);
+				if (TextUtils.isEmpty(urlData)){
+					urlData = code;
+				}
+				Log.d("test->", "before nav activity ");
+
+				WXPreLoadManager.getInstance().preLoad(urlData);
 				Toast.makeText(this, rawResult.getText(), Toast.LENGTH_SHORT).show();
 				Intent intent = new Intent(CaptureActivity.this, WXPageActivity.class);
 				intent.setData(Uri.parse(code));