最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【基本解决】原生Android端多次调用ReactJS的H5中的页面加载完毕的回调函数

Android crifan 3663浏览 0评论

原生端,android的代码:

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        showPd();
        if (newProgress == 100) {
            webView.loadUrl("javascript:loginCallback(" + "’" + GsonUtil.creatSipmleGson().toJson(LoginUserManager.getInstance()) + "’" + ")");
            L.e("logininfo",GsonUtil.creatSipmleGson().toJson(LoginUserManager.getInstance()));
            hidePd();
        }
    }
});

Reactjs中H5的页面中:

。。。
export default class App extends Component {
。。。
  constructor(props) {
    console.log("App constructor");
    super(props);
    autoBind(this);
    this.loginCallback = this.loginCallback.bind(this);
  }
  componentWillMount() {
    console.log("App componentWillMount");
    console.log(window);
    console.log(window.userInfoDict);
    window.loginCallback = this.loginCallback;
  }
  //Native(iOS/Android):loginCallback(String userInfoJsonStr);
  loginCallback(userInfoJsonStr){
    console.log(`loginCallback: userInfoJsonStr=${userInfoJsonStr}`);
    alert(userInfoJsonStr);
    // let userInfoDict = Object(userInfoJsonStr);
    let userInfoDict = JSON.parse(userInfoJsonStr);
    console.log(userInfoDict);
    // alert(userInfoDict);
    console.log(typeof(userInfoDict)); //object
    console.log(userInfoDict.currentCowfarmId);
    console.log(userInfoDict.cowfarmList);
    console.log(typeof(userInfoDict.cowfarmList)); //object
    window.userInfoDict = userInfoDict;
    console.log(window.userInfoDict);
    // alert(window.userInfoDict);
  }

可以实现基本的效果:

当原生Android端登录完毕后,判断H5中浏览器内容加载完毕,然后调用loginCallback,把用户信息的json字符串传递到H5端

但是有个问题:

之后,每次(比如通过Prect-router中的route(“/xx”)去)页面切换时,都会导致此处的触发回调

所以希望去解决此问题。

只实现:

原生端能判断webview第一次加载完毕才调用回调函数

之后webview中页面切换时,不要调用。

看了android代码,感觉:onProgressChanged不像是 webviewLoadCompleted

之类的含义,而是进度有变化时就调用。

搜:

WebChromeClient onProgressChanged

503596 – Multiple callbacks from onProgressChanged with 100% in WebView – chromium – Monorail

“Note that there is a separate callback `onPageFinished` which is really indicating that the page’s resources have finished loading. `onProgressChanged` is intended to be used to update loading progress bar. ”

这样的解释才对。

Issue 1080143003: Move DidStartLoading, DidStopLoading, DidChangeLoadProgress to RFHI. – Code Review

onPageFinished

DidStopLoading

Android WebView顶部进度条 – 简书

WebViewClient与WebChromeClient的区别 – 泡在网上的日子

android – Display webview with dialog progress and webchrome client – Stack Overflow

Android WebView WebChromeClient : inaccurate progress value in onProgressChanged() – Stack Overflow

WebChromeClient | Android Developers

竟然只有:

 onProgressChanged

没有:

onPageFinished

DidStopLoading

之类的。

WebView之加载网页时增加进度提示 – 飘杨…… – 博客园

好像只能通过:

if(newProgress >= 100){

去判断页面加载完毕了?

webchromeclient on page finished

Android Webview: Detect when rendering is finished – Stack Overflow

WebChromeClient用onProgressChanged且:

           if (progress == 100) {

               // do something

           }

WebViewClient用onPageFinished

android – How to listen for a WebView finishing loading a URL? – Stack Overflow

有多个页面(iframe?)的话,会有多个:onPageFinished(和onPageStarted)

-》那如果换用onPageFinished 貌似和onProgressChanged progress >= 100 也没啥区别了,都是导致多次调用啊。

android – Are WebViewClient and WebChromeClient mutually exclusive? – Stack Overflow

WebChromeClient | Android Developers

WebView的几个常见功能使用 – 一片纯净的热土 – CSDN博客

貌似真的是没有好的解决办法:

暂时只能靠ReactJS中H5去手动判断是否第一次调用了。。。

也想到了:

如果让android端去加上判断,只有当加载了首页 然后onProgressChanged中progress是100,才调用

-》但是也是会存在,如果移动端H5中,有其他情况,比如刷新,退出后再登录等,去加载首页,还是会多次调用,还是需要H5端去做限制,还是无法完全避免H5端不需要额外特殊判断

WebChromeClient onProgressChanged progress 100 multiple call

Android WebView WebChromeClient : inaccurate progress value in onProgressChanged() – 推Code

就是用我上面想到的办法:

判断是否加载的是:某个页面,比如主页

如果不是,则不去调用

Android Splash screen while loading webview – Recalll

【总结】

感觉Android中,不论是用

(1)WebChromeClient用onProgressChanged

且加上判断:

           if (progress == 100) {

               // do something

           }

(2)WebViewClient用onPageFinished

结果都是:

会调用多次

即使android端加了判断,是某个页面的url(比如首页”/“),但是也还是无法完全避免多次加载,比如,刷新页面了之类的。

所以,干脆还是放在H5页面中去加上判断吧:

export default class App extends Component {
  state = {
    curUrl : "/"
  };
  constructor(props) {
。。。
    window.hasCallLoginCallback = false;
  }
  //Native(iOS/Android):loginCallback(String userInfoJsonStr);
  loginCallback(userInfoJsonStr){
    if (window.hasCallLoginCallback) {
      return;
    }
    window.hasCallLoginCallback = true;
。。。
    let userInfoDict = JSON.parse(userInfoJsonStr);
。。。
    window.userInfoDict = userInfoDict;
。。。
  }

然后其他地方,比如退出登录处,再去重置该变量:

  onConfirmLogout(){
。。。
    //clear this to make sure following loginCallback will be called in app.js
    window.hasCallLoginCallback = false;
    this.logout();
  }

即可基本实现:

只调用一次loginCallback,别处不会再次触发。且,退出登录后,重新登录进去后,还是要正常的继续调用一次loginCallback的。

转载请注明:在路上 » 【基本解决】原生Android端多次调用ReactJS的H5中的页面加载完毕的回调函数

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
90 queries in 0.176 seconds, using 22.15MB memory