欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Webview的postUrl与loadUrl加载页面实例

程序员文章站 2022-06-04 18:01:30
关于android的webview,用过的想必都不会陌生。这里我就不说webview的基本用法了,想要知道的可以去网上百多,有很多介绍webview基本用法的。本文要介绍的主要是在项目过程中使用web...

关于android的webview,用过的想必都不会陌生。这里我就不说webview的基本用法了,想要知道的可以去网上百多,有很多介绍webview基本用法的。

本文要介绍的主要是在项目过程中使用webview的posturl遇到的坑。

1、使用场景如下:

webview在加载h5链接时,默认是使用loadurl进行加载,如果你设置了缓存属性(进行缓存),在显示的h5页面内点击跳转到另外一个页面后,按回退键,可以正常的返回到上一个页面,因为进行了缓存设置。但是如果使用posturl进行加载,即使你设置的缓存属性是进行设置,当你调转到另外一个页面后,按回退键,不会缓存之前的页面,而是重新调用posturl进行加载。这时问题就来了,同样是进行加载,第一次的posturl能够正常加载,重新加载会加载失败,没有内容显示。是不是很有意思,为什么会出现这样的情况呢,通过抓包发现,虽然加载的是同样一个链接,但是重新加载的请求属性为空,导致加载失败。

2、如何解决:

既然找到了原因,请求属性为空,肯定是有解决办法的,那就手动设置请求属性,重新加载。如何手动设置,首先你肯定是要能够拿到请求的所有内容和参数。用过webview的人相必都很熟悉它的setwebviewclient方法。该方法内部有shouldinterceptrequest方法能够拿到请求的所有内容。不多说了,先上代码。

public webresourceresponse shouldinterceptrequest(webview view, webresourcerequest request) {
  if(build.version.sdk_int >= 21){
   if(!request.getmethod().equalsignorecase("post")){
    return super.shouldinterceptrequest(view, request);
   }
  }
  dataoutputstream os = null;
  try {
   url murl = new url(url);
   httpurlconnection connection = (httpurlconnection) murl.openconnection();
   connection.setdoinput(true);
   connection.setdooutput(true);
   connection.setusecaches(false);
   connection.setrequestmethod("post");
   if(build.version.sdk_int >= 21){
    iterator headerkeys=request.getrequestheaders().keyset().iterator();
    while(headerkeys.hasnext()){
     string key=headerkeys.next();
     connection.setrequestproperty(key,request.getrequestheaders().get(key));
    }
   }
   connection.setrequestproperty("content-type","application/x-www-form-urlencoded");
   os = new dataoutputstream(connection.getoutputstream());
 
   os.write(encodingutils.getbytes(postdata, "base64"));
   os.flush();
   return new webresourceresponse("text/html", connection.getcontentencoding(), connection.getinputstream());
  } catch (exception e) {
   e.printstacktrace();
  }finally {
   if(os!=null){
    try {
     os.close();
    } catch (ioexception e) {
     e.printstacktrace();
    }
   }
  }
  return super.shouldinterceptrequest(view, request);
 }
});

webview.posturl(url, encodingutils.getbytes(postdata, "base64"));

该方法有个缺陷,只在android 5.0.0以上的api才有,5.0.0以下的api是没有此方法的,这也是一个坑,不能兼容所有机型。通过该方法中的setrequestproperty方法重新设置了请求属性,然后使用posturl进行重新加载,可以解决按回退键后页面的重新恢复。注意,由于post加载是不能缓存的,因此在设置缓存属性时一定要设置成重新加载属性。

3、解决后出现的问题:

问题看似解决了,但是此方法会有坑。如果你仔细研究该方法,你会发现shouldinterceptrequest方法是在整个加载过中都调用了的。如果你进行抓包,你会发现,从开始加载链接到h5页面中加载的每一个请求,该方法都会被调用,简单的说就是有多少个请求,该方法就会调用多少次。如果你的页面中还有一次post请求,那么问题就来了,你需要将第二次post请求的请求内容与第一次的进行对比,对比后选择到底是加载第一次的页面,还是加载第二次的页面,否则就会默认加载第一次的post页面。

4、结论

webview的h5页面加载最好使用loadurl方式,如果使用posturl方式进行加载,你需要重写整个setwebviewclient方法,当中会出很多坑,不建议这样做。

以上这篇android webview的posturl与loadurl加载页面实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。