Android WebView加載本地html並實現Java與JS交互

最近作的一個項目中,用到自定義地圖,將自定義地圖轉換成html頁面,如今須要作的是如何將本地的html加載到android中,並能夠實現交互。javascript

相關講解:css

其實webview加載資源的速度並不慢,可是若是資源多了,固然就很慢。圖片、css 、js 、html這些資源每一個大概須要10-200ms ,通常都是30ms就ok了。不過webview是必須等到所有資源都完成加載,纔會進行渲染的,因此加載的速度很重要!從Google上咱們瞭解到,webview加載頁面的順序是:先加載html,而後從裏面解析出css、js文件和頁面上的圖片資源進行加載。若是webkit的緩存裏面有,就不加載。加載完這些資源以後,就進行css的渲染和js的執行。CSS的渲染通常不須要很長時間,幾十毫秒就ok。關鍵是js的執行,若是用了jQuery,則執行起來須要5-6秒。而在這段時間,若是不在webview裏設置背景,網頁部分是白色的,很難看。這是一個很糟糕的用戶體驗。因此建議若是用網頁佈局程序,最好別用那些龐大的js框架。最好使用原生的js寫業務腳本,以提高加載速度,改善用戶體驗。html

在Android上怎樣實現JAVA和JS交互呢?java

Android的webview是基於webkit內核的,webview中集成了js與java互調的接口函數,經過addJavas criptInterface方法,能夠將Java的類註冊進webkit,給網頁上的js進行調用,並且還能夠經過loadUrl方法給webkit傳遞一個URL,供瀏覽器來進行解析,實現Java和js交互。android

要想運行網頁上的js腳本,webview必須設置支持Javas cript。web

Java代碼:1mWebview.getSettings().setJavascriptEnabled(true);json

而後是設置webView要加載的網頁:瀏覽器

  web的網頁:webView.loadUrl("http://www.google.com");緩存

  本地的網頁:webView.loadUrl("file:///android_asset/XX.html"); //本地的存放在:assets文件夾中微信

webview作完基本的初始化後咱們還要要給它,加進一個回調的代理類JavascriptInterface,並給它一個調用的名稱:ncp

Java代碼:1mWebView.addJavas criptInterface(new Javas criptInterface(),"ncp");

Javas criptInterface能夠是一個普通的Java類,類實現的方法,都可被js回調:

Java代碼:

final class Javas criptInterface {

  public int callOnJs() {

    return 1000;

  }

  public void callOnJs2(String mode) {

    //TODO

  }

}

Java要調用js的方法,只需知道js的方法名稱便可:

  Java代碼:1mWebView.loadUrl("javas cript:onSaveCallback()");

js 這邊就更簡單(存在的版本兼容問題,參考使用WebView過程當中的問題總結):

  JS代碼:  

window.onload = function(){

  document.getElementById('btn_1').addEventListener('click', onBtnClick, false);

  var _int_value = window.ncp.callOnJs();

  alert("get int from java:" + _int_value );

}

function onBtnClick() {

  window.ncp.callOnJs2("click");

}

Java和js交互有如下一些特色:

1.Java 調用 js 裏面的函數,速度並不使人滿意,大概一次一兩百毫秒吧,若是要作交互性很強的事情,這種速度會讓人瘋掉的。而反過來就不同了, js 去調 java 的方法,速度很快,基本上 40-50 毫秒一次。因此儘可能用 js 調用 java 方法,而不是 java 去調用 js 函數。

2.Java 調用 js 的函數,沒有返回值,而 Js 調用 java 方法,能夠有返回值。返回值能夠是基本類型、字符串,也能夠是對象。若是是字符串,有個很討厭的問題,第 3 點我會講的。若是是對象,這個對象會被轉換爲 js 的對象,直接能夠訪問裏面的方法。可是我不推薦 java 返回給 js 的是對象,除非是必須。由於 js 收到 java 返回的對象,會產生一些交換對象,而若是這些對象的數量增長到了 500 或 600 以上,程序就會出問題。因此儘可能返回基本數據類型或者字符串。

3.Js 調用 Java 的方法,返回值若是是字符串,你會發現這個字符串是 native 的,不能對它進行一些修改操做,好比想對它 substr ,取不到。怎麼解決呢?轉成 locale 的。使用 toLocaleString() 函數就能夠了。不過這個函數的速度並不快,轉化的字符串若是不少,將會很耗費時間。

下面是一個具體的例子:

1.新建assets文件夾,將本地html頁面拷貝到該文件夾下。

2.xml文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    tools:context=".MainActivity" >  
  
    <TextView  
        android:id="@+id/tv"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="@string/hello_world" />  
    <WebView  
        android:layout_below="@+id/tv"  
        android:id="@+id/webview"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent"  
    />  
  
</RelativeLayout> 

3.java文件

package com.example.webview_workflowy;  
  
import android.app.Activity;  
import android.content.Intent;  
import android.net.Uri;  
import android.os.Bundle;  
import android.webkit.WebView;  
import android.widget.Toast;  
  
public class MainActivity extends Activity {  
  
    private WebView webView;  
  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        //加載頁面  
        webView = (WebView) findViewById(R.id.webview);  
        //容許JavaScript執行  
        webView.getSettings().setJavaScriptEnabled(true);  
        //找到Html文件,也能夠用網絡上的文件  
        webView.loadUrl("file:///android_asset/index.html");  
        // 添加一個對象, 讓JS能夠訪問該對象的方法, 該對象中能夠調用JS中的方法  
        webView.addJavascriptInterface(new Contact(), "contact");  
    }  
  
    private final class Contact {  
        //JavaScript調用此方法撥打電話  
        public void call(String phone) {  
//            startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + phone)));  
            Toast.makeText(MainActivity.this, phone, Toast.LENGTH_LONG).show();  
        }  
  
        //Html調用此方法傳遞數據  
        public void showcontacts() {  
            String json = "[{\"name\":\"zxx\", \"amount\":\"9999999\", \"phone\":\"18600012345\"}]";   
            // 調用JS中的方法  
            webView.loadUrl("javascript:show('" + json + "')");  
        }  
          
        public void toast(String str){  
            Toast.makeText(MainActivity.this, "aaaaaaaaaaaa  --- " + str, Toast.LENGTH_LONG).show();  
        }  
    }  
  
}  

4.html

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
<html>  
    <head>  
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
        <title>Insert title here</title>  
        <script type="text/javascript">  
            function show(jsondata){              
                    var jsonobjs = eval(jsondata);  
                    var table = document.getElementById("personTable");  
                    for(var y=0; y<jsonobjs.length; y++){  
                        var tr = table.insertRow(table.rows.length);   
                        var td1 = tr.insertCell(0);  
                        var td2 = tr.insertCell(1);  
                        td2.align = "center";  
                        var td3 = tr.insertCell(2);  
                        td3.align = "center";  
                        td1.innerHTML = jsonobjs[y].name;   
                        td2.innerHTML = jsonobjs[y].amount;   
                        td3.innerHTML = "<a href='javascript:contact.call(\""+ jsonobjs[y].phone+ "\")'>"+ jsonobjs[y].phone+ "</a>";   
                    }  
            }  
        </script>  
    </head>  
    <body onload="javascript:contact.showcontacts()">  
       <button id="button" onclick = "javascript:contact.toast('123')">haha</button>  
       <table border="0" width="100%" id="personTable" cellspacing="0">  
            <tr>  
                <td width="30%">姓名</td>  
                <td width="30%" align="center">存款</td>  
                <td align="center">電話</td>  
            </tr>  
        </table>  
    </body>  
</html>  

 

若是此文對您有幫助,微信打賞我一下吧~

相關文章
相關標籤/搜索