Android 使用 AsyncTask 通过 jsoup 获取 url 时应用崩溃
Android app crashes when using AsyncTask for fetching an url with jsoup
所以应用程序在加载时显示了对话框,但随后崩溃了。我决定不使用这些技术的原因是因为我必须加载动态变化的 html,并且我想缓存大量 CSS 文件,所以我认为将它们作为资产包括在内是一个好主意。我使用 Jsoup 是因为我无需下载完整内容即可获得 html 页面。
这是代码:
public class MyWebViewFragment extends Fragment {
ProgressDialog mProgress;
WebView webview;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.web_fragment, container,
false);
Bundle bundle = getArguments();
String url = bundle.getString("url");
webview = (WebView) rootView.findViewById(R.id.webview1);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
mProgress = ProgressDialog.show(getActivity(), "Loading",
"Please wait for a moment...");
fetchUrl thread = (fetchUrl) new fetchUrl().execute();
Document doc = thread.getDoc();
String htmlData = null;
doc.head().getElementsByTag("link").remove();
doc.head().appendElement("link").attr("rel", "stylesheet").attr("type", "text/css").attr("href", "style.css");
htmlData = doc.outerHtml();
//TODO fetchURL here
webview.loadDataWithBaseURL("file:///assets/", htmlData, "text/html", "UTF-8", null);
// webview.loadUrl(url);
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//TODO add assets loading he instead of urlLoad
//view.loadUrl(url);
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (mProgress.isShowing()) {
mProgress.dismiss();
}
}
});
return rootView;
}
class 扩展 AsybcTask:
private class fetchUrl extends AsyncTask<Void, Void, Document>{
Document doc;
@Override
protected Document doInBackground(Void... param) {
try {
doc = Jsoup.connect("http://example.ch").userAgent("Chrome").get();//use url when ready
} catch (IOException ex) {
}
return doc;
}
}
以及错误日志:
--------- beginning of crash
E/AndroidRuntime( 5125): FATAL EXCEPTION: main
E/AndroidRuntime( 5125): Process: com.flexenergy.swapp, PID: 5125
E/AndroidRuntime( 5125): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.flexenergy.swapp/com.flexenergy.swapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'org.jsoup.nodes.Element org.jsoup.nodes.Document.head()' on a null object reference
E/AndroidRuntime( 5125): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
E/AndroidRuntime( 5125): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
E/AndroidRuntime( 5125): at android.app.ActivityThread.access0(ActivityThread.java:151)
E/AndroidRuntime( 5125): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
E/AndroidRuntime( 5125): at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 5125): at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime( 5125): at android.app.ActivityThread.main(ActivityThread.java:5257)
E/AndroidRuntime( 5125): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 5125): at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime( 5125): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/AndroidRuntime( 5125): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime( 5125): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'org.jsoup.nodes.Element org.jsoup.nodes.Document.head()' on a null object reference
E/AndroidRuntime( 5125): at com.flexenergy.swapp.MyWebViewFragment.onCreateView(MyWebViewFragment.java:49)
E/AndroidRuntime( 5125): at android.app.Fragment.performCreateView(Fragment.java:2053)
E/AndroidRuntime( 5125): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
E/AndroidRuntime( 5125): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
E/AndroidRuntime( 5125): at android.app.BackStackRecord.run(BackStackRecord.java:834)
E/AndroidRuntime( 5125): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
E/AndroidRuntime( 5125): at android.app.Activity.performStart(Activity.java:6005)
E/AndroidRuntime( 5125): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
E/AndroidRuntime( 5125): ... 10 more
W/ActivityManager( 1219): Force finishing activity 1 com.flexenergy.swapp/.MainActivity
I/Choreographer( 1219): Skipped 30 frames! The application may be doing too much work on its main thread.
E/EGL_emulation( 919): tid 919: eglCreateSyncKHR(1237): error 0x3004 (EGL_BAD_ATTRIBUTE)
AsyncTask 是主线程的并发进程,因此要使用该计算的结果,您需要等到它完成他的工作。
您正在尝试调用 doc.head()
,但 doc 是空引用,因为 asyncTask 尚未完成,因此尚未初始化 doc
。
在 AsyncTask 的 OnPostExecute(result)
方法中用 doc
做你的事情,这样你就可以确保 doc
被正确初始化。
所以应用程序在加载时显示了对话框,但随后崩溃了。我决定不使用这些技术的原因是因为我必须加载动态变化的 html,并且我想缓存大量 CSS 文件,所以我认为将它们作为资产包括在内是一个好主意。我使用 Jsoup 是因为我无需下载完整内容即可获得 html 页面。 这是代码:
public class MyWebViewFragment extends Fragment {
ProgressDialog mProgress;
WebView webview;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.web_fragment, container,
false);
Bundle bundle = getArguments();
String url = bundle.getString("url");
webview = (WebView) rootView.findViewById(R.id.webview1);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
mProgress = ProgressDialog.show(getActivity(), "Loading",
"Please wait for a moment...");
fetchUrl thread = (fetchUrl) new fetchUrl().execute();
Document doc = thread.getDoc();
String htmlData = null;
doc.head().getElementsByTag("link").remove();
doc.head().appendElement("link").attr("rel", "stylesheet").attr("type", "text/css").attr("href", "style.css");
htmlData = doc.outerHtml();
//TODO fetchURL here
webview.loadDataWithBaseURL("file:///assets/", htmlData, "text/html", "UTF-8", null);
// webview.loadUrl(url);
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//TODO add assets loading he instead of urlLoad
//view.loadUrl(url);
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (mProgress.isShowing()) {
mProgress.dismiss();
}
}
});
return rootView;
}
class 扩展 AsybcTask:
private class fetchUrl extends AsyncTask<Void, Void, Document>{
Document doc;
@Override
protected Document doInBackground(Void... param) {
try {
doc = Jsoup.connect("http://example.ch").userAgent("Chrome").get();//use url when ready
} catch (IOException ex) {
}
return doc;
}
}
以及错误日志:
--------- beginning of crash
E/AndroidRuntime( 5125): FATAL EXCEPTION: main
E/AndroidRuntime( 5125): Process: com.flexenergy.swapp, PID: 5125
E/AndroidRuntime( 5125): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.flexenergy.swapp/com.flexenergy.swapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'org.jsoup.nodes.Element org.jsoup.nodes.Document.head()' on a null object reference
E/AndroidRuntime( 5125): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
E/AndroidRuntime( 5125): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
E/AndroidRuntime( 5125): at android.app.ActivityThread.access0(ActivityThread.java:151)
E/AndroidRuntime( 5125): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
E/AndroidRuntime( 5125): at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 5125): at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime( 5125): at android.app.ActivityThread.main(ActivityThread.java:5257)
E/AndroidRuntime( 5125): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 5125): at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime( 5125): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/AndroidRuntime( 5125): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime( 5125): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'org.jsoup.nodes.Element org.jsoup.nodes.Document.head()' on a null object reference
E/AndroidRuntime( 5125): at com.flexenergy.swapp.MyWebViewFragment.onCreateView(MyWebViewFragment.java:49)
E/AndroidRuntime( 5125): at android.app.Fragment.performCreateView(Fragment.java:2053)
E/AndroidRuntime( 5125): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
E/AndroidRuntime( 5125): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
E/AndroidRuntime( 5125): at android.app.BackStackRecord.run(BackStackRecord.java:834)
E/AndroidRuntime( 5125): at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
E/AndroidRuntime( 5125): at android.app.Activity.performStart(Activity.java:6005)
E/AndroidRuntime( 5125): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
E/AndroidRuntime( 5125): ... 10 more
W/ActivityManager( 1219): Force finishing activity 1 com.flexenergy.swapp/.MainActivity
I/Choreographer( 1219): Skipped 30 frames! The application may be doing too much work on its main thread.
E/EGL_emulation( 919): tid 919: eglCreateSyncKHR(1237): error 0x3004 (EGL_BAD_ATTRIBUTE)
AsyncTask 是主线程的并发进程,因此要使用该计算的结果,您需要等到它完成他的工作。
您正在尝试调用 doc.head()
,但 doc 是空引用,因为 asyncTask 尚未完成,因此尚未初始化 doc
。
在 AsyncTask 的 OnPostExecute(result)
方法中用 doc
做你的事情,这样你就可以确保 doc
被正确初始化。