Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在设备旋转/拆分视图后使用ViewModel还原Android WebView页面_Javascript_Android_Webview_Rotation_Viewmodel - Fatal编程技术网

Javascript 在设备旋转/拆分视图后使用ViewModel还原Android WebView页面

Javascript 在设备旋转/拆分视图后使用ViewModel还原Android WebView页面,javascript,android,webview,rotation,viewmodel,Javascript,Android,Webview,Rotation,Viewmodel,我使用WebView显示数据,数据通过JS函数得到增强。在设备旋转之前,它可以正常工作。使用ViewModel保存页面数据并在配置更改后恢复它似乎是正确的想法,但我遇到了问题,页面没有恢复。我将代码简化为一个简单的示例,包括在这里(无XML布局) DataStore类存储数据,覆盖ViewModel,只需在列表中存储一些字符串 package com.automationce.labyrinth.webview; import android.arch.lifecycle.ViewModel

我使用WebView显示数据,数据通过JS函数得到增强。在设备旋转之前,它可以正常工作。使用ViewModel保存页面数据并在配置更改后恢复它似乎是正确的想法,但我遇到了问题,页面没有恢复。我将代码简化为一个简单的示例,包括在这里(无XML布局)


DataStore类存储数据,覆盖ViewModel,只需在列表中存储一些字符串

package com.automationce.labyrinth.webview;

import android.arch.lifecycle.ViewModel;
import java.util.ArrayList;
import java.util.List;

/* The idea is to use ViewModel to store page data
* so it can be restored on device rotate/split view */
public final class DataStore extends ViewModel {
   public List<String> records = new ArrayList<>();

   public DataStore() {
      super();
   }
}
其想法是在ViewModel中保存数据,并在创建过程中恢复数据。我花了一段时间才明白为什么它不起作用。数据存储在旋转期间确实会被保留(我可以看到数据存储对象中的所有历史数据),但尽管我看到正在执行的恢复代码,但它从未在SimpleWebView中呈现


原因是,虽然JavaScript函数确实正确写入了页面,但我在页面实际呈现之前从MainActivity.OnCreate调用restore()。JS函数被调用并很快被忽略,因为实际上,就WebView而言,页面并不存在(我认为)。令人惊讶的是,这实际上在我使用的大多数模拟器上都起了作用——现在我认为它不应该起作用,我也不知道它为什么起作用——直到我在一个物理设备(Galaxy S7)上运行它,在那里恢复被忽略了


我的解决方案是为我的SimpleWebView提供一个新的WebViewClient并重写其OnPageFinished方法,并在该方法中在页面加载完成后恢复页面内容。SimpleView构造函数(“以下代码中的firstView”布尔标志在设备旋转后首次重新加载视图后失效):

在设备旋转/拆分窗口之后,现在可以从持久数据重建网页。它似乎工作得很好,没有任何明显的负载延迟(我现在处理的是相对较小的数据集)

我一直在寻找解决方案,我真的不想在OnSaveInstanceState/onRestoreInstanceState中保存和还原整个页面的字符串内容,因为在这种情况下,这对我没有任何好处-我会有数据,但在呈现页面后仍需要还原它

我从集体中寻求智慧的话语:

  • 我的分析正确吗
  • 有没有更好的处理方法
  • 是否有什么事情(令人不快的生产代码惊喜,等等——我对Android很陌生)需要我注意
谢谢,Jiri

package com.automationce.labyrinth.webview;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.webkit.WebView;

public final class SimpleWebView extends WebView {
   // Use to keep and restore data between config changes
   // (not related to browser history by any means)
   private DataStore dataStore;

   public SimpleWebView(Context context, AttributeSet attrs) {
      super(context, attrs);
      setBackgroundColor(Color.LTGRAY);
      getSettings().setJavaScriptEnabled(true);
      setWebContentsDebuggingEnabled(true);

      // Define style, write JS function(s)
      String content = "<!DOCTYPE html><html><head>" +
            "<style>" +
            "span { font-size: " +
            0.875 +
            "em; } " +
            "</style>" +
            "</head><body id=\"body\">" +
            jsFunctions() + "</body></html>";

      loadDataWithBaseURL(null, content, "text/html", "utf-8", null);
   }

   // JS function(s) as written to the page
   private String jsFunctions() {
      return "<script>" +
            "function append (string) { " +
            "var body = document.getElementById('body');" +
            "var block = document.createElement('span');" +
            "var text = document.createTextNode(string);" +
            "var br = document.createElement('br'); " +
            "block.appendChild(text);" +
            "block.appendChild(br); " +
            "body.appendChild(block);" +
            "block.scrollIntoView();" +
            " }" +
            "</script>";
   }

   public void setHistory (final DataStore storedData) {
      dataStore = storedData;
   }

   // Restore page from DataStore data
   public void restore() {
      for(String record : dataStore.records) {
         evaluateJavascript("append ('" + record + "');", null);
      }
   }

   // Append new data to existing page
   public void append(final String string) {
      dataStore.records.add(string);
      evaluateJavascript("append ('" + string + "');", null);
   }
}
package com.automationce.labyrinth.webview;

import android.arch.lifecycle.ViewModelProviders;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

   private SimpleWebView pageView;
   private Button appendButton;
   private int counter;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      DataStore storedData = ViewModelProviders.of(this).get(DataStore.class);

      appendButton = findViewById(R.id.button);
      pageView = findViewById(R.id.webView);
      pageView.setHistory(storedData);
      pageView.restore();

      appendButton.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
            append();
         }
      });
   }

   private void append() {
      counter++;
      pageView.append("Some kind of new text " + counter);
   }
}
   public SimpleWebView(Context context, AttributeSet attrs) {
      super(context, attrs);
      setBackgroundColor(Color.LTGRAY);
      getSettings().setJavaScriptEnabled(true);
      setWebContentsDebuggingEnabled(true);

      setWebViewClient(new WebViewClient() {
         @Override
         public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            Log.v("PAGE", "finished");
            if (firstView) {
               ((SimpleWebView)view).restore();
            }
         }
      });
     .
     .