# 小程序后台预加载方案

本章描述用到的对象的说明:
JsView.java: Java 接口文档
window.JsvCoreApi: window.JsvCoreApi 文档

# 预加载流程Android端,方案一 (独立构造 JSViewParent)

[!TIP] SDK版本要求>= com.tvcode.js_view_app:JSViewApp:1.4.754.20260525

  • 构造一个 JSViewParent
// Devtools 调试端口
JSViewCoreManager.getInstance().setDebugPort(9336);
mJsViewParent = new JSViewParent(getApplicationContext());
1
2
3
  • 监听小程序事件

JSViewParent有着与MainPageProxy类似的监听接口 JsViewParent.registerMiniAppObserver() JsViewParent.unregisterMiniAppObserver() JsViewParent.registerMiniAppLifecycleCallback() JsViewParent.unregisterMiniAppLifecycleCallback()

mMainJsViewRef = null; // 记录jsview句柄, 用于处理可视化展示

mJsViewParent.registerMiniAppObserver(new MiniAppObserver() {
    @Override
    public void onMiniAppStartLoad(MiniApp miniApp) {
        // 记录JsView句柄, 用于 toggleViewVisible(View.VISIBLE) 控制
        mMainJsViewRef = miniApp.getJsView();

        // 将jsview初始化为不可视模式, 让js能获知此不可视状态,这样避免一些不必要的加载,比如图片
        mMainJsViewRef.toggleViewVisible(View.GONE);
    }

    @Override
    public void onMiniAppVisibleReady(MiniApp miniApp) {
        // js在收到 toggleViewVisible(View.VISIBLE) 后并完成所有视觉效果调整后
        // 会回调此接口
    }

    @Override
    public void onMiniAppLoadProgress(MiniApp miniApp, int progress) {

    }

    @Override
    public void onMiniAppLoadSuccess(MiniApp miniApp) {

    }

    @Override
    public void onMiniAppLoadFail(MiniApp miniApp, int errorCode) {

    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  • 加载小程序
mJsViewParent.loadUrl("http://xxxxxxx",null);
1

点击查看 JsViewParent.loadUrl()

  • 显示小程序: 使用mMainPageProxy.onCreate传入mJsViewParent

mJsViewParent将会被 add 到 rootView中。

mMainPageProxy.onCreate(mSavedInstanceState, (ViewGroup) rootView,
                null, mJsViewParent);

// 通知js进入显示状态
mMainJsViewRef.toggleViewVisible(View.VISIBLE);

1
2
3
4
5
6
  • 再次进行显隐控制

但因为初始化时没有和Activity绑定, 仍然需要通过 mMainJsViewRef.toggleViewVisible() 来控制内容的显隐.

在Activity的Stop时, 通过 mMainJsViewRef.toggleViewVisible(View.GONE); 控制为不可见.

在Activity的Start时, 通过 mMainJsViewRef.toggleViewVisible(View.VISIBLE); 控制为可见. 此动作会让 JS 端收到可视状态变为 show 的通知, JS 端需在完成视觉效果调整后再次调用 notifyVisibleReady(), Java 端会再次收到 MiniAppObserver.onMiniAppVisibleReady 回调.

  • 释放资源

假如mJsViewParent没有被传入mMainPageProxy.onCreate,mJsViewParent里加载的小程序将无法自动释放。
调用clearJSView 主动释放所有小程序。

mJsViewParent.clearJSView();
1

# 预加载流程Android端,方案二 (隐藏 JsView)

// 创建JsView控制句柄
JsView mJsviewRef;

...

// 通过Intent的方式正常触发jsview加载

...
mMainPageProxy.setMiniAppObserver(new MiniAppObserver() {
    @Override
    public void onMiniAppStartLoad(MiniApp miniApp) {
        // 获取jsview句柄
        mJsviewRef = miniApp.getJsView();

        // 将jsview初始化为不可视模式, 让js能获知此不可视状态
        mJsviewRef.toggleViewVisible(View.GONE);
    }

    @Override
    public void onMiniAppVisibleReady(MiniApp miniApp) {
        // js 在收到 toggleViewVisible(View.VISIBLE) 后并完成所有视觉效果调整后
        // 会回调此接口
    }
});

...

// 恢复可视窗口
mJsviewRef.toggleViewVisible(View.VISIBLE);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 预加载流程(js端)

需要考虑如下注意点:

  1. 因为处于后台运行,标签不会加载而触发onload, 所以notifyPageLoaded的处理不要依靠此类onload,可以window.JsvCoreApi.getVisibility() 来识别并调整时机。
  2. 关键的Event注册, 放到notifyPageLoaded之前, 在notifyPageLoaded都会被java端完整保存不会丢失。
  3. 建议在首次加载前, 停留在空页面的路由中, 以减少内存资源占用。同时不要开启setInterval这种重复时钟处理以减少cpu开销

样例代码:

import { jJsvRuntimeBridge } from "jsview";

let firstTimeShow: bool = true;

// 在notifyPageLoaded, 把诸如来自java的跳转需求进行监听
let targetRoute:string = "";
window.JsvCoreApi.addEventListener("RouteTo", (info)=>{
    if (firstTimeShow) {
        // 记录跳转目标, 在首次展示时才进行跳转, 解析类似乎 startPage=XXXXXXX 的内容, 转成路由参数
        targetRoute = parseStartPage(info.newPath);
    } else {
        // 已经启动完成, 可以直接进行跳转
        router.push(parseStartPage(info.newPath));
    }
})

// 若原 notifyPageLoaded 依赖 <img> 标签的onload时
if (firstTimeShow && window.JsvCoreApi.getVisibility() != "show") {
    // 启动时为不可见状态

    // 启动时为不可见状态时, 认为是首次启动
    jJsvRuntimeBridge.notifyPageLoaded();
} else {
    // 启动时已经为可见状态
    firstTimeShow = false;

    // 可以继续使用在 onload 后调用 notifyPageLoaded 的逻辑
    ...
}

// 监听可视状态变化
window.JsvCoreApi.onVisibilityChange((newStatus)=>{
    if (newStatus.status == "show") {
        if (firstTimeShow) {
            // 首次展示, 根据 targetRoute 进行跳转
            if (targetRoute) {
                router.push(targetRoute);
            }
            firstTimeShow = false;
        }

        // 界面准备完整后, 通过 notifyVisibleReady 通知到 MiniAppObserver.onMiniAppVisibleReady()
        // Activity 每次从 Stop 恢复为 Start 时也需要再次调用
        jJsvRuntimeBridge.notifyVisibleReady();
    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# java如何向js小程序发送消息

向小程序发送消息, 是在 MiniAppObserver.onMiniAppStartLoad 拿到JsView句柄后, 通过 JsViewRef.emitEvent 来发送消息通知。

// emitEvent举例: 
EventPack ev1 = new EventPack().put("newPath", "startPage=XXXXXXX");
mJsviewRef.emitEvent("RouteTo", ev1);
1
2
3

特别说明, js端务必在调用notifyPageLoaded前, 要先把对此类emitEvent的接受通过 window.JsvCoreApi.addEventListener把消息注册上,这样在notifyPageLoaded前发生的所有emitEvent都不会丢失。

Last Updated: 5/27/2026, 10:32:59 AM