【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式

news2024/9/22 13:32:44

文章目录

  • webView
    • 使用步骤
    • 示例
  • HttpURLConnection
    • 使用步骤
    • 示例
    • GET请求
    • POST请求
  • okHttp
    • 使用步骤
    • 1. 添加依赖
    • 2. 创建OkHttpClient实例
    • 3. 创建Request对象构建请求
    • 4. 发送请求
    • 5. 获取响应
  • Pull解析方式
    • 1. 准备XML数据
    • 2. 创建数据类
    • 3. 使用Pull解析器解析XML

webView

WebView 是 Android 中用于显示网页内容的组件。它允许你在应用内嵌入一个浏览器,加载并显示 HTML、JavaScript、CSS 等网页内容。以下是使用 WebView 的步骤和一些示例代码。

使用步骤

  1. 在布局文件中添加 WebView

    • 在 XML 布局文件中定义一个 WebView 控件。
  2. 在 Activity 或 Fragment 中初始化 WebView

    • 获取布局中的 WebView 实例,并配置其设置。
  3. 加载网页内容

    • 使用 loadUrl() 方法加载网页 URL,或使用 loadData() 方法加载 HTML 字符串。
  4. 配置设置(可选)

    • 配置 JavaScript 支持、缓存设置等。
  5. 处理 WebView 的事件(可选)

    • 设置 WebViewClientWebChromeClient 来处理网页加载过程中的事件和 JavaScript 对话框。
  6. 权限

    AndroidManifest.xml 中添加互联网权限:

<uses-permission android:name="android.permission.INTERNET"/>

示例

  1. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>
  1. 在 Activity 中使用 WebView

MainActivity.java 中初始化并使用 WebView

import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);

        // 启用 JavaScript 支持
        webView.getSettings().setJavaScriptEnabled(true);

        // 设置 WebViewClient 以处理网页加载事件
        webView.setWebViewClient(new WebViewClient());

        // 加载网页内容
        webView.loadUrl("https://www.baidu.com");
    }
}

配置 WebView 设置

  • JavaScript 支持:启用 JavaScript 支持以处理动态网页内容。

    webView.getSettings().setJavaScriptEnabled(true);
    
  • 缓存设置:可以设置缓存模式来优化加载速度。

    webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
    
  • 自定义用户代理:可以设置用户代理字符串。

    webView.getSettings().setUserAgentString("Custom User Agent");
    

处理 WebView 事件

  • WebViewClient:用于处理网页加载过程中的事件。
    • onPageStarted(WebView view, String url, Bitmap favicon):当页面开始加载时调用。
    • onPageFinished(WebView view, String url):当页面加载完成时调用。
    • shouldOverrideUrlLoading(WebView view, WebResourceRequest request):处理 URL 跳转请求。

权限

AndroidManifest.xml 中添加互联网权限:

<uses-permission android:name="android.permission.INTERNET"/>

HttpURLConnection

HttpURLConnection 是 Android 中用于处理 HTTP 请求的类。它提供了一种在应用中发送和接收 HTTP 请求和响应的方法。

使用步骤

1. 创建 URL 对象

  • 使用指定的 URL 创建 URL 对象。

2. 打开连接

  • 使用 URL.openConnection() 打开连接,并将其转换为 HttpURLConnection

3. 配置连接参数

  • 设置请求方法(如 GET 或 POST)。
  • 配置连接和读取超时时间等参数。

4. 发送请求

  • 获取输入流并读取服务器响应。

5. 处理响应

  • 读取输入流中的数据,并进行处理。

6. 关闭连接

  • 关闭输入流和断开连接。
// 创建一个URL对象,指定请求的URL地址
URL url = new URL("http://www.baidu.com");
// 打开一个到该URL的HTTP连接,并将其转换为HttpURLConnection
HttpURLConnection connection = (HttpURLConnection) url.openConnection();

// 设置请求方法为GET
connection.setRequestMethod("GET");
// 设置连接超时时间为8秒
connection.setConnectTimeout(8000);
// 设置读取超时时间为8秒
connection.setReadTimeout(8000);

// 获取服务器响应的输入流
InputStream inputStream = connection.getInputStream();
// 字节流->字符流->字符缓冲流
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
   sb.append(line);
}
return sb.toString();
// 断开与服务器的连接
connection.disconnect();

示例

获取百度网页源码

Android 9.0(API level 28)及更高版本中,对所有的网络请求必须使用HTTPS

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    // 显示服务器响应的文本视图
    private TextView tv;
    // 发送请求的按钮
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = findViewById(R.id.btn_send);
        tv = findViewById(R.id.tv_response);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // 在新线程中执行网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 初始化HTTP连接和读取器
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try {
                    // 创建URL对象,指定请求的URL
                    URL url = new URL("https://www.baidu.com");
                    // 打开连接
                    connection = (HttpURLConnection) url.openConnection();
                    // 设置请求方法为GET
                    connection.setRequestMethod("GET");
                    // 设置连接超时和读取超时时间
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    // 获取输入流,用于读取服务器响应
                    InputStream inputStream = connection.getInputStream();
                    // 将输入流包装为缓冲读取器
                    reader = new BufferedReader(new InputStreamReader(inputStream));
                    StringBuilder sb = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                    }
                    // 在UI线程中更新界面
                    showResponse(sb.toString());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    if (connection != null)
                        connection.disconnect();
                }
            }
        }).start();

    }

    // 在UI线程中更新响应文本
    private void showResponse(final String string) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tv.setText(string);
            }
        });
    }
}

申请权限

<uses-permission android:name="android.permission.INTERNET"/>

GET请求

主要目的:从服务端获取符合条件的数据。

image-20240806201410364

POST请求

主要目的:向服务端提交数据。

场景举例:用户注册的时候,填写表格里一堆的信息(姓名、性别、年龄、电话…),这些都是要提交给服务端的数据

表单

image-20240806201938856

image-20240806203014879

okHttp

使用步骤

1. 添加依赖

implementation 'com.squareup.okhttp3:okhttp:4.10.0'

2. 创建OkHttpClient实例

OkHttpClient client = new OkHttpClient();

这是进行网络请求的客户端,配置了连接池、超时设置等参数。

3. 创建Request对象构建请求

Request request = new Request.Builder()
        .url("https://www.baidu.com")
        .build();

使用 Request.Builder 来构建 HTTP 请求,包括设置 URL 和请求方法(GET、POST 等)。

4. 发送请求

调用execute方法发送请求并获取服务器返回数据

Response response = client.newCall(request).execute();

newCall(request).execute() 会同步地执行请求,并返回一个 Response 对象。异步执行可以使用 enqueue 方法。

5. 获取响应

final String responseData = response.body().string();

Response 对象中获取响应体,并将其转为字符串。响应体只能读取一次,所以多次使用它,可能需要将其保存到其他地方。

更新 UI

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        tv.setText(responseData);
    }
});

由于网络请求是在子线程中执行的,任何更新 UI 的操作都必须在主线程中进行。使用 runOnUiThread 来确保 UI 更新在主线程中执行。

示例

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView tv;      
    private Button button;  

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);  

        button = findViewById(R.id.btn_send);
        tv = findViewById(R.id.tv_response);

        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // 在子线程中进行网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 创建 OkHttpClient 实例
                OkHttpClient client = new OkHttpClient();

                // 构建一个 GET 请求,指定请求的 URL
                Request request = new Request.Builder()
                        .url("https://www.baidu.com")
                        .build();

                try {
                    // 执行网络请求,并获取响应
                    Response response = client.newCall(request).execute();

                    // 获取响应体的字符串形式
                    final String responseData = response.body().string();

                    // 使用 runOnUiThread() 确保 UI 更新在主线程中进行
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // 更新 TextView 的内容为网络请求的响应数据
                            tv.setText(responseData);
                        }
                    });
                } catch (IOException e) {
                    // 捕获并打印可能发生的 IOException
                    e.printStackTrace();
                }
            }
        }).start();  // 启动子线程进行网络请求
    }
}

Pull解析方式

Pull解析器是一种基于事件的解析方式,当解析器读取到XML文档中的开始标签、结束标签或文本内容时,会触发相应的事件。它是Android中处理XML的推荐方法之一,因其速度快且内存占用低。

1. 准备XML数据

假设我们有如下的XML数据:

<users>
    <user>
        <name>John Doe</name>
        <age>30</age>
        <married>true</married>
    </user>
    <user>
        <name>Jane Doe</name>
        <age>25</age>
        <married>false</married>
    </user>
</users>

2. 创建数据类

我们需要创建一个数据类来表示解析后的数据:

public class User {
    private String name;
    private int age;
    private boolean married;

    // ...
}

3. 使用Pull解析器解析XML

在Activity或Fragment中使用Pull解析器解析XML数据:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // XML字符串
        String xmlData = "<users><user><name>John Doe</name><age>30</age><married>true</married></user><user><name>Jane Doe</name><age>25</age><married>false</married></user></users>";

        try {
            // 解析XML
            List<User> users = parseXML(xmlData);
            // 遍历解析得到的用户列表并打印日志
            for (User user : users) {
                Log.d("MainActivity", "User Name: " + user.getName());
                Log.d("MainActivity", "User Age: " + user.getAge());
                Log.d("MainActivity", "User Married: " + user.isMarried());
            }
        } catch (XmlPullParserException | IOException e) {
            e.printStackTrace();
        }
    }

    // 解析XML数据
    private List<User> parseXML(String xmlData) throws XmlPullParserException, IOException {
        List<User> users = null; // 用于存储用户对象的列表
        User currentUser = null; // 当前正在解析的用户对象
        boolean insideUser = false; // 标记当前是否在<user>标签内

        // 创建XmlPullParserFactory和XmlPullParser实例
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser parser = factory.newPullParser();
        parser.setInput(new StringReader(xmlData)); // 设置解析器的输入为XML字符串

        int eventType = parser.getEventType(); // 获取事件类型
        while (eventType != XmlPullParser.END_DOCUMENT) { // 遍历整个文档
            String tagName;
            switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    users = new ArrayList<>(); // 初始化用户列表
                    break;
                case XmlPullParser.START_TAG:
                    tagName = parser.getName(); // 获取标签名
                    if (tagName.equals("user")) { // 如果是<user>标签
                        insideUser = true; // 标记进入<user>标签
                        currentUser = new User(); // 创建一个新的User对象
                    } else if (currentUser != null) {
                        // 仅当在<user>标签内部时,才解析这些标签
                        if (tagName.equals("name") && insideUser) {
                            currentUser.setName(parser.nextText());
                        } else if (tagName.equals("age") && insideUser) {
                            currentUser.setAge(Integer.parseInt(parser.nextText()));
                        } else if (tagName.equals("married") && insideUser) {
                            currentUser.setMarried(Boolean.parseBoolean(parser.nextText()));
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    tagName = parser.getName(); // 获取结束标签的名称
                    if (tagName.equals("user") && currentUser != null) {
                        users.add(currentUser); // 将解析完毕的用户对象添加到列表中
                        insideUser = false; // 标记离开<user>标签
                    }
                    break;
            }
            eventType = parser.next(); // 获取下一个事件
        }
        return users; // 返回解析得到的用户列表
    }
}
  • 创建XmlPullParserFactoryXmlPullParser实例。
  • 设置解析器的输入为XML字符串。
  • 使用while循环遍历整个XML文档,根据事件类型(开始标签、结束标签、文本等)进行相应处理。
  • 在遇到<user>标签时,创建新的User对象并开始填充数据。
  • 在遇到</user>标签时,将填充完毕的User对象添加到List<User>中。
  • 解析完成后,返回包含所有用户信息的列表。


感谢您的阅读
如有错误烦请指正


参考:

  1. 31.2-Android网络请求的Get与Post方法(1)_哔哩哔哩_bilibili

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1990221.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三大浏览器Google Chrome、Edge、Firefox内存占用对比

问题 Chrome、Edg、Firefox三家究竟谁的占用少 结论 打开一个页面内存占用 Firefox>Edge>Chrome 打开打量页面内存占用 Firefox>Chrome>Edge 从监视器可以看到Edge增加一个页面增加一个页面不到100M而其它浏览器需要150M左右;Firefox浏览器主线程内存占用800M比…

Java之TCP网络编程

TCP网络编程 1 概述 在TCP通信协议下&#xff0c;计算机网络中不同设备上的应用程序之间可以通信&#xff0c;通信时需严格区分客户端&#xff08;Client&#xff09;与服务器端&#xff08;Server&#xff09;。 在Java中&#xff0c;对于这样基于TCP协议下连接通信的客户端…

数据结构-常见排序的七大排序

1.排序的概念及其运用 1.1排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a;假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录…

Arkose 验证码:网络抓取工具的最佳实践

网络爬虫已经成为企业和开发人员最常用的工具&#xff0c;用于有效地从网络中收集数据。当然&#xff0c;大家都会遇到的最常见挑战是大量的 CAPTCHA 出现&#xff0c;这会使工作流程陷入停滞。其中&#xff0c;Arkose Labs Captcha&#xff08;称为 Funcaptcha&#xff09;以其…

探索N卡录制:游戏录屏工具会是网页录屏的最佳伴侣吗?

在这个数字时代&#xff0c;无论是游戏玩家、教育工作者还是内容创作者&#xff0c;高质量的录屏工具都是必不可少的。NVIDIA显卡&#xff08;简称N卡&#xff09;以其卓越的图形处理能力而闻名&#xff0c;而N卡录制功能则进一步扩展了其应用范围&#xff0c;特别是在游戏录屏…

【SpringBoot 属性加载机制】

SpringBoot 属性加载 一个 SpringBoot 应用的配置属性可以有多种不同的来源, 比如可以来自操作系统的环境变量, 比如可以来自 application.yaml 文件; 每一种不同的属性来源, 都会被 SpringBoot 封装成一个PropertySource对象, 保存在 Environment 对象的 PropertySources 类型…

proteus仿真c51单片机(三)多定时任务的编程——时分秒发生器

实验步骤 1、打开PROTEUS软件选取元件&#xff0c;连线绘制电路图。 2、打开KEIL软件编制程序进行调试、编译。 3、将编译的HEX代码装入PROTEUS软件绘制的电路图的单片机中。 4、仿真运行观察实验现象&#xff0c;若与要求的实验现象不同&#xff0c;检查程序和电路图找…

Linux目录结构常用命令和文件管理解析

一.Linux目录结构 bin:binary二进制&#xff0c;普通用户执行命令都在这里 boot:和计算机启动的相关文件都放这 dev:device设备、驱动、硬件 etc:配置文件也叫控制台文件 home:来装用户自己的文件的&#xff0c;普通用户的家目录主目录&#xff0c;每个普通用户进来都有自…

PythonStudio 控件使用常用方式(十二)TMaskEdit

PythonStudio是一个极强的开发Python的IDE工具&#xff0c;它使用的是Delphi的控件&#xff0c;常用的内容是与Delphi一致的。但是相关文档并一定完整。现在我试试能否逐步把它的控件常用用法写一点点&#xff0c;也作为PythonStudio的参考。 从1.2.1版开始&#xff0c;Python…

Android compose OutlinedTextField 输入框设置固定高度后,内容挤压显示不全

原因&#xff1a; decorationBox里边contentPadding() 默认为16.dp internal val TextFieldPadding 16.dp 修改方法1&#xff1a; copy OutlinedTextField.kt 源码&#xff0c;decorationBox的contentPadding参数开放出来 /*** author 创建人&#xff1a;蒙石瑞* date …

【大模型从入门到精通11】openAI API 提示链的力量2

这里写目录标题 提示链的力量&#xff1a;阅读和处理JSON字符串基于产品信息生成用户响应综合性的客户服务互动结论理论问题 提示链的力量&#xff1a;阅读和处理JSON字符串 当处理复杂的工作流程时&#xff0c;通常会以JSON格式传递数据。以下示例演示了如何将JSON字符串转换…

【Linux QT】添加Json-C库

前言 在Linux应用开发中&#xff0c;Linux设备和服务器通信时&#xff0c;两者之间数据的传输通常采用JSON数据格式来作为载体&#xff0c;便于两者之间的数据交互。当设备端接收到服务端下发的JSON数据&#xff0c;设备端需要对JSON格式的数据进行解析&#xff1b;当设备端需要…

Java设计模式(命令模式)

定义 将一个请求封装为一个对象&#xff0c;从而让你可以用不同的请求对客户进行参数化&#xff0c;对请求排队或者记录请求日志&#xff0c;以及支持可撤销的操作。 角色 抽象命令类&#xff08;Command&#xff09;&#xff1a;声明用于执行请求的execute方法&#xff0c;通…

CSS实现hover时文本上下出现线条

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>复杂Hover效果示例</title><style>p {f…

【案例38】Can’t get connection from database 排查详细记录

问题现象 客户要搭建灰度环境&#xff0c;启动后&#xff0c;登录超级管理员报连接不上数据库的错误。 Can’t get connection from database(XXX) 问题分析 1、一般碰到这个问题&#xff0c;初步就开始怀疑是sysconfig数据源不通导致的。 发现数据源是通的。 2、在sysconf…

【案例40】Apache中mod_proxy模块的使用

NC中间件 应用场景&#xff1a;配置了apache的情况&#xff0c;包括uap集群&#xff0c;配置https等场景下均适用&#xff1b;如果是单机&#xff08;NC单结点情况不存在问题&#xff0c;则不用配置这项; was环境也不用配置此项。&#xff09; 解决方案&#xff1a;按如下两…

【15.PIE-Engine案例——加载Landsat 8 SR数据集】

加载Landsat 8 SR数据集 原始路径 欢迎大家登录航天宏图官网查看本案例原始来源 最终结果 具体代码 /*** File : Landsat8SRImages* Time : 2020/7/21* Author : piesat* Version : 1.0* Contact : 400-890-0662* License : (C)Copyright 航天宏图信息技…

【C++】BFS解决Floodfill问题

目录 Floodfill算法介绍 解决方法 BFS 图画渲染 算法思路&#xff1a; 代码实现&#xff1a; 岛屿数量 算法思路 代码实现 岛屿的最大面积 算法思想 代码实现 被围绕的区域 算法思路 代码实现 总结&#xff1a; Floodfill算法介绍 Floodfill翻译过来就是“洪…

serial靶机渗透~反序列化

反序列化又叫对象注入&#xff0c;序列化在内部没有漏洞&#xff0c;漏洞产生是因为程序在处理对象、魔术函数以及序列化相关的问题导致的&#xff0c;当传给 unserialize()的参数可控时&#xff0c;那么用户就可以注入 payload&#xff0c;进行反序列化的时候就可能触发对象中…

【iOS】AutoreleasePool自动释放池的实现原理

目录 ARC与MRC项目中的main函数自动释放池autoreleasepool {}实现原理AutoreleasePoolPage总结 objc_autoreleasePoolPush的源码分析autoreleaseNewPageautoreleaseFullPageautoreleaseNoPage autoreleaseFast总结 autorelease方法源码分析objc_autoreleasePoolPop的源码分析po…