# 小程序后台预加载方案
本章描述用到的对象的说明:
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());
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) {
}
});
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);
- 显示小程序: 使用
mMainPageProxy.onCreate传入mJsViewParent
mJsViewParent将会被 add 到 rootView中。
mMainPageProxy.onCreate(mSavedInstanceState, (ViewGroup) rootView,
null, mJsViewParent);
// 通知js进入显示状态
mMainJsViewRef.toggleViewVisible(View.VISIBLE);
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();
# 预加载流程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);
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端)
需要考虑如下注意点:
- 因为处于后台运行,
标签不会加载而触发onload, 所以notifyPageLoaded的处理不要依靠此类onload,可以window.JsvCoreApi.getVisibility() 来识别并调整时机。
- 关键的Event注册, 放到notifyPageLoaded之前, 在notifyPageLoaded都会被java端完整保存不会丢失。
- 建议在首次加载前, 停留在空页面的路由中, 以减少内存资源占用。同时不要开启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();
}
})
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);
2
3
特别说明, js端务必在调用notifyPageLoaded前, 要先把对此类emitEvent的接受通过 window.JsvCoreApi.addEventListener把消息注册上,这样在notifyPageLoaded前发生的所有emitEvent都不会丢失。