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


    webView

    WebViewAndroid 中用于显示网页内容的组件。它允许你在应用内嵌入一个浏览器,加载并显示 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. 布局文件
    
    <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 Doename>
            <age>30age>
            <married>truemarried>
        user>
        <user>
            <name>Jane Doename>
            <age>25age>
            <married>falsemarried>
        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 = "John Doe30trueJane Doe25false";
    
            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; // 标记当前是否在标签内
    
            // 创建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")) { // 如果是标签
                            insideUser = true; // 标记进入标签
                            currentUser = new User(); // 创建一个新的User对象
                        } else if (currentUser != null) {
                            // 仅当在标签内部时,才解析这些标签
                            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; // 标记离开标签
                        }
                        break;
                }
                eventType = parser.next(); // 获取下一个事件
            }
            return users; // 返回解析得到的用户列表
        }
    }
    
    • 创建XmlPullParserFactoryXmlPullParser实例。
    • 设置解析器的输入为XML字符串。
    • 使用while循环遍历整个XML文档,根据事件类型(开始标签、结束标签、文本等)进行相应处理。
    • 在遇到标签时,创建新的User对象并开始填充数据。
    • 在遇到标签时,将填充完毕的User对象添加到List中。
    • 解析完成后,返回包含所有用户信息的列表。


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


    参考:

    1. 31.2-Android网络请求的Get与Post方法(1)_哔哩哔哩_bilibili
  • 相关阅读:
    程序员VS产品经理的世纪之争
    Angular 18+ 高级教程 – 国际化 Internationalization i18n
    多角度分析!解决Android手机无法连接Wi-Fi的方法指南!
    git入门
    Dockerfile(基于jdk17)
    CMT2380F32模块开发4-UART例程
    工业物联网案例:智能工厂设备无人值守系统方案
    创建order\stock模块 Dubbo 负载均衡
    【漏洞复现】SolarWinds——任意文件读取
    基于Echarts实现可视化数据大屏治理运行分析云图
  • 原文地址:https://blog.csdn.net/Patrick_yuxuan/article/details/140980939