本文共 4408 字,大约阅读时间需要 14 分钟。
一、坑场景复现
源于,运行代码都没有输出,一直在研究为什么会出现这样的结果。
在测试过程中使用WebEngine的html加载,使用WebEngine的url加载,使用WebView加载url,使用仅Scene装载WebView(没有加入Stage或者没有运行stage.show()方法),还有使用Scene装载WebView(加入Stage并且运行stage.show()方法)等等,其中只有WebEngine的html加载、Scene装载WebView(加入Stage并且运行stage.show()方法)有输出文档信息,其余都没有输出结果。
(1)代码对比
1、WebEngine 加载html
import com.sun.javafx.application.PlatformImpl;import javafx.concurrent.Worker;import javafx.scene.web.WebEngine;public class A { public static void main(String[] args) throws InterruptedException { PlatformImpl.startup(()->{ doDom(); System.err.println("finish"); }); } public static void doDom() { WebEngine webEngine = new WebEngine(); webEngine.getLoadWorker().stateProperty() .addListener((obs, oldValue, newValue) -> { if (newValue == Worker.State.SUCCEEDED) { String html = (String) webEngine .executeScript("document.documentElement.outerHTML"); System.out.println(html); System.exit(0); } System.out.println(newValue + " "); }); // addListener() String s="\n" + "\n" + "\n" + "我的第一个 HTML 页面 \n" + "\n" + "\n" + "\n" + "body 元素的内容会显示在浏览器中。
\n" + "title 元素的内容会显示在浏览器的标题栏中。
\n" + "\n" + "\n" + "\n"; webEngine.loadContent(s); }}
2、WebEngine 加载url
import com.sun.javafx.application.PlatformImpl;import javafx.concurrent.Worker.State;import javafx.scene.web.WebEngine;public class Test { public static void main(String[] args) throws InterruptedException { PlatformImpl.startup(() -> { doDom(); System.err.println("finish"); }); } public static void doDom(){ WebEngine webEngine = new WebEngine(); webEngine.getLoadWorker().stateProperty() .addListener((obs, oldValue, newValue) -> { if (newValue == State.SUCCEEDED) { String html = (String) webEngine .executeScript("document.documentElement.outerHTML"); System.out.println(html); System.exit(0); } System.out.println(newValue + " "); }); // addListener() webEngine.load("https://www.w3cschool.cn/java/javafx-webengine.html"); }}
(2)输出结果
1、WebEngine 加载html:
SCHEDULED RUNNING finish我的第一个 HTML 页面 body 元素的内容会显示在浏览器中。
title 元素的内容会显示在浏览器的标题栏中。
Process finished with exit code 0
2、WebEngine 加载url:
SCHEDULED RUNNING finish
程序运行不能结束。
如果在WebEngin类的dispatchLoadEvent(long frame, int state, String url, String contentType, double workDone, int errorCode)方法里面debug运行,则输出
SCHEDULED RUNNING finish...//内容太多此处省略Process finished with exit code 0
二、分析原因
通过run和debug模式的运行的结果不同,让我意识到WebEngine 变量是局部变量,里面的监听事件还没有执行完就被gc回收。
备注:Stage primaryStage是局部变量,没有调用show方法,很快就被gc回收,里面包含的WebEngine、WebView和Scene也会被gc回收,故看不到输出。
以前还有遇见过这样的现象,比如Javafx的MediaPlayer播放几秒钟音乐就停止了,因为这个有播放声音比较明显,可以找到是gc回收了MediaPlayer。
import com.sun.javafx.application.PlatformImpl;import javafx.concurrent.Worker.State;import javafx.scene.web.WebEngine; public class Test { public static void main(String[] args) throws InterruptedException { PlatformImpl.startup(() -> { doDom(); System.out.println("finish"); }); } static WebEngine webEngine;//webEngine必须要有引用在使用,不能定义成局部变量,否则被gc回收就没有输出结果 public static void doDom(){ //WebEngine webEngine = new WebEngine();//以前定义成局部变量,被gc回收了 webEngine = new WebEngine(); webEngine.getLoadWorker().stateProperty() .addListener((obs, oldValue, newValue) -> { if (newValue == State.SUCCEEDED) { String html = (String) webEngine .executeScript("document.documentElement.outerHTML"); System.out.println(html); System.exit(0); } System.out.println(newValue + " "); }); // addListener() webEngine.load("https://www.w3cschool.cn/java/javafx-webengine.html"); //webEngine.loadContent(html);//直接加载html }}
转载地址:https://maokun.blog.csdn.net/article/details/85221621 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!