Skip to content

14.视图绑定与网络编程

1. 视图绑定

视图绑定  | Android 开发者  | Android Developers (google.cn)

通过视图绑定viewBinding功能,您可以更轻松地编写可与视图交互的代码。在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。

1.1 打开 viewBinding

java
	//默认是关闭的,手动打开
    viewBinding{
        enabled=true
    }

1.2 viewBinding的使用

自动将xml文件生成java类  类的名字以xml的名字+Binding

也正是如此让我们不需要再使用findViewById()来获取控件,直接类名.组件ID就可以获取到控件的引用

java
 //改造activity
activityMainBinding=ActivityMainBinding.inflate(getLayoutInflater());
setContentView(activityMainBinding.getRoot());

//优势一:无需findViewById,简化控件获取
//优势二:避免报空指针,控件管理更方便,有条理
activityMainBinding.txtViewId.setText("HNUCM");

2. WebView

在 WebView 中编译 Web 应用  | Android 开发者  | Android Developers (google.cn)

如果希望在客户端应用中提供 Web 应用(或只是网页),则可以使用 WebView 执行该操作。WebView 类是 Android 的 View 类的扩展,可将网页显示为 Activity 布局的一部分。它不会包含功能全面的网络浏览器的任何功能,例如导航控件或地址栏。WebView 默认只显示网页。

android里可以嵌套网页,如微信公众号,小程序

2.1 app嵌入网页

在xml文件中添加一个webView控件

要在 WebView 中加载网页,使用 loadUrl()方法:

java
activityMainBinding.webViewId.loadUrl("http://www.qq.com");
java

activityMainBinding.webViewId.loadUrl("http://www.qq.com");

activityMainBinding.webViewId.setWebViewClient(new WebViewClient(){
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
});

这样我们可以看到,成功将网页嵌入到了app中,不过网页仍然是以网页端显示

2.2 设置显示样式

通过如下设置可以使样式和手机端样式显示

java
WebSettings webSettings = activityMainBinding.webViewId.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);

//设置自适应屏幕,两者合用
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
//自适应屏幕
activityMainBinding.webViewId.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

//缩放操作
webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

//其他细节操作
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
webSettings.setAllowFileAccess(true); //设置可以访问文件
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

//优先使用缓存
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//缓存模式如下:
//LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
//LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
//LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
//LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
//不使用缓存
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);

2.3 嵌入自定义(本地)网页

创建一个assets文件夹

Tips:Assets 目录是 Android 的一种特殊目录,用于放置 APP 所需的固定文件,且该文件被打包到 APK 中时,不会被编码到二进制文件

将自己写好的student.html(这是我web课的一个小作业)网页脚本,复制到assets文件夹下

需要修改一下文件的路径:

java
activityMainBinding.webViewId.loadUrl("file:///android_asset/student.html");

运行同样可以显示

可以看到在html(web)中的语法都能在android中生效,跳转同样的可以通过<a></a>标签实现

除此之外webView提供了跳转的方法

先在xml创建两个按钮来监听点击事件

webView提供goBack()goForward()方法监听网页间的跳转

java
activityMainBinding.button.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
         activityMainBinding.webViewId.goBack();
     }
 });

activityMainBinding.button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        activityMainBinding.webViewId.goForward();
    }
});

可以看到无论是用<a></a>标签还是,Android原生的按钮监听都能实现网页的跳转

3. 思索&下期预告

理想情况下,Android中的所有UI全部都可以通过webView使用网页来实现,但为什么web没有取代Android开发?那是不是前端的工程师都可以兼职开发Android,干嘛还要发展Android呢?

4.完整代码

MainActivity代码

java
public class MainActivity extends AppCompatActivity {

    //viewBinding
    //自动将xml文件生成java类  类的名字以xml的名字+Binding
    ActivityMainBinding activityMainBinding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //改造activity
        activityMainBinding=ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(activityMainBinding.getRoot());

        //优势一:无需findViewById,简化控件获取
        //优势二:避免报空指针,控件管理更方便,有条理
        //activityMainBinding.txtViewId.setText("HNUCM");


        //问题一:并不是嵌入在app中
        activityMainBinding.webViewId.loadUrl("file:///android_asset/student.html");

        activityMainBinding.webViewId.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });


        WebSettings webSettings = activityMainBinding.webViewId.getSettings();
        //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
        webSettings.setJavaScriptEnabled(true);

        //设置自适应屏幕,两者合用
        webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
        webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小
        //自适应屏幕
        activityMainBinding.webViewId.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
        webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

        //缩放操作
        webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
        webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
        webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

        //其他细节操作
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存
        webSettings.setAllowFileAccess(true); //设置可以访问文件
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
        webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
        webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

        //优先使用缓存
        webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
        //缓存模式如下:
        //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
        //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
        //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
        //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
        //不使用缓存
        webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);

        activityMainBinding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                activityMainBinding.webViewId.goBack();
            }
        });

        activityMainBinding.button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                activityMainBinding.webViewId.goForward();
            }
        });

    }
}

activity_main.xml代码

java
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <WebView
        android:id="@+id/webViewId"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:text="返回"
        app:layout_constraintEnd_toStartOf="@+id/button2"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/webViewId" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="前进"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button"
        app:layout_constraintTop_toTopOf="@+id/button" />

</androidx.constraintlayout.widget.ConstraintLayout>

student.html代码

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        th{
            border: 1px solid black;
            background-color: antiquewhite;
            padding: 5px;
        }
        td{
            border: 1px solid black;
            font-family: 'Courier New', Courier, monospace;
            padding: 4px;
        }
        table{
            border-collapse: collapse;
            width: 90%;
            margin: auto;
        }
        div{
            border: 1px solid black;
            width: 60%;
            margin: auto;
        }

    </style>

</head>
<body style="text-align:center">
    <script>
        function add(obj){
            
            var vstu_id=formNode.stu_id.value;
            var vstu_name=formNode.stu_name.value;
            var vstu_sex=formNode.stu_sex.value;
            if(vstu_id==""||vstu_name==""||vstu_sex==""){
                alert("数据不能为空!");
            }else{

            
                alert(vstu_id+' '+vstu_name+' '+vstu_sex)

                var vtable1=document.getElementById('table1'); 

                var vtr=document.createElement('tr');
                

                var vtd_id=document.createElement('td');
                vtd_id.innerText=vstu_id;

                var vtd_name=document.createElement('td');
                vtd_name.innerText=vstu_name;

                var vtd_sex=document.createElement('td');
                vtd_sex.innerHTML=vstu_sex;

                var vth_del=document.createElement('td');
                
                var va=document.createElement('a');
                va.setAttribute("href","JavaScript:void(0)");
                va.setAttribute("onclick","del(this)");
                va.innerHTML="删除";
                vth_del.appendChild(va);

                vtr.appendChild(vtd_id);
                vtr.appendChild(vtd_name);
                vtr.appendChild(vtd_sex);
                vtr.appendChild(vth_del);

                vtable1.appendChild(vtr);
            }

        }

        function del(obj){
            var msg="确定删除这条数据吗?";

            if(confirm(msg)==true){
                var vth_delNode=obj.parentNode;
                var vtrNode=vth_delNode.parentNode;
                var vtable1=vtrNode.parentNode;
                vtable1.removeChild(vtrNode);
            }
        }
    </script>
    
    <div>

        <a href ="file:///android_asset/student2.html">跳转</a>
        <form name="formNode" style="margin-top: 15px">
            编号:<input type="text" maxlength="3" size="4" name="stu_id">
            姓名:<input type="text" maxlength="8" size="4" name="stu_name">
            性别:<input type="text" size="4" name="stu_sex">
            <input type="button" value="添加" onclick="add(this)">
        </form>
        <table style="margin-top: 20px; margin-bottom: 20px;" id="table1">
            <caption style="font-size: 20px;">学生成绩表</caption>
            <tr>
                <th>编号</th>
                <th>姓名</th>
                <th>性别</th>
                <th>操作</th>
            </tr>
    
            <tr>
                <td>001</td>
                <td>lixu</td>
                <td>nan</td>
                <td><a onclick="del(this)" href="JavaScript:void(0)">删除</a></td>
            </tr>
        </table>
        
    </div>
</body>
</html>