我知道这已经被问了太多次,并且SO充满了类似的问题。我经历了大部分时间,并且我已经研究了这个问题几天了,我还没有找到明确的解决方案。
我可以轻松避免将configChanges="orientation|screenSize"
添加到包含WebView的活动中的所有麻烦;我已对此进行了测试,并且按预期工作(WebView没有重新加载)。 但我真的想避免这种解决方案。
这是我当前的WebView实现:
public class BrowserFragment extends Fragment {
private WebView mWebView;
public BrowserFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (mWebView == null) {
mWebView = new WebView(getActivity());
}
return mWebView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
});
mWebView.getSettings().setAllowFileAccess(true);
mWebView.getSettings().setBuiltInZoomControls(false);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setSupportZoom(false);
if (savedInstanceState == null) {
mWebView.loadUrl("http://developer.android.com/");
} else {
mWebView.restoreState(savedInstanceState);
}
}
@Override
public void onResume() {
mWebView.onResume();
super.onResume();
}
@Override
public void onPause() {
super.onPause();
mWebView.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mWebView.saveState(outState);
}
@Override
public void onDestroyView() {
if (getRetainInstance() && mWebView.getParent() instanceof ViewGroup) {
((ViewGroup) mWebView.getParent()).removeView(mWebView);
}
super.onDestroyView();
}
}
对于MainActivity
,除了将内容视图设置为以下布局文件之外,没有任何其他内容:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="@+id/fragment_browser"
android:name="com.example.app.BrowserFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</merge>
请注意,我保留了片段实例,并且还保存了WebView的状态,因此我可以延迟恢复相同的状态。这是文档对restoreState
方法所说的内容:
从给定的Bundle恢复此WebView的状态。这种方法 旨在用于onRestoreInstanceState(Bundle),应该是 调用以恢复此WebView的状态。如果是之后的话 这个WebView有机会构建状态(加载页面,创建一个 后退/前进列表等)可能存在不良副作用。 请 请注意,此方法不再为此恢复显示数据 web视图。
意思是,显示数据不会被恢复,但滚动位置之类的东西会(我也测试了这个并且它运行得很好)。这就是为什么我创建WebView的新实例的原因,只有在null
期间它onCreateView
onDestroyView
并在import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.ListView;
import android.widget.Toast;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class ExDownloaderActivity extends AsyncTask<Void, Integer, String>
{
Context context;
String address;
ListView expenseListView;
ProgressDialog progressDialog;
public ExDownloaderActivity(Context context, String address, ListView exCategoryListView)
{
this.context = context;
this.address = address;
this.expenseListView = exCategoryListView;
}
//B4 JOB STARTS
@Override
protected void onPreExecute()
{
super.onPreExecute();
progressDialog = new ProgressDialog(context);
progressDialog.setTitle("Fetch Data");
progressDialog.setMessage("Fetching Data...Please wait");
progressDialog.show();
}
@Override
protected String doInBackground(Void... params)
{
String data = downloadData();
return data;
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String string)
{
super.onPostExecute(string);
progressDialog.dismiss();
if(string != null)
{
ExParserActivity parser = new ExParserActivity(context, string, expenseListView);
parser.execute();
}
else
{
Toast.makeText(context, "Unable to download data",Toast.LENGTH_LONG).show();
}
}
private String downloadData()
{
//connect and get a stream of data
InputStream inputStream = null;
//to store each line
String line = null;
try
{
URL url = new URL(address);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
inputStream = new BufferedInputStream(httpURLConnection.getInputStream());
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
StringBuffer stringBuffer = new StringBuffer();
if(bufferedReader!= null)
{
while ((line = bufferedReader.readLine()) != null)
{
stringBuffer.append(line + "\n");
}
}
else
{
return null;
}
return stringBuffer.toString();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if(inputStream != null)
{
try
{
inputStream.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
return null;
}
}
期间从父视图中删除它。这取自这个答案:https://stackoverflow.com/a/32801278/40480
此机制将使旋转过程更加平滑(没有它,显示完整的空白页面),但不会阻止WebView重新加载页面。
任何想法我怎么可能解决这个问题?
答案 0 :(得分:1)
我有类似的问题。这有点晚了但是我的解决方法与你的相似,但是再次将webview添加到onCreateView的布局中:
如果已经创建(重新创建活动),只需添加到框架并使其无效(对于在旋转时重绘webview很重要)
mFrame = (FrameLayout) mView.findViewById(R.id.dq_fragment_browser_common_frame);
if (mWebView == null){
mWebView = new CommonWebView(getContext());
mFrame.addView(mWebView,0);
} else {
mFrame.addView(mWebView,0);
mWebView.invalidate();
}
在您的情况下,我在OnDestroyView()中从框架中删除webview,以便能够在onCreateView中再次添加它:
@Override
public void onDestroyView() {
mFrame.removeView(mWebView);
super.onDestroyView();
}
注意:我不会在重新加载页面时保存并存储webview状态(至少在我的情况下)。此外,滚动位置通常在纵向/横向上不匹配,但在我检查过的情况下Chrome中的问题也相同。
问候。