Android网络请求,Retrofit,OKHttp学习

发布于:2025-07-25 ⋅ 阅读:(14) ⋅ 点赞:(0)

Retrofit、OkHttp(层网络请求,拦截器处理 Header、缓存)、子线程处理相关事务

1.WebView

WebView可以在我们自己的应用程序中嵌入一个浏览器并且展示网页

新建一个项目,修改主活动布局代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <WebView
        android:id="@+id/web_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

可以看到在布局中使用了WebView,修改MainActivity

package com.example.webviewtest;

import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        WebView webView = findViewById(R.id.web_view);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setWebViewClient(new WebViewClient());
        webView.loadUrl("https://www.baidu.com");
    }
}

MainActivity中,首先获取WebView实例,调用WebView的getSettings()方法可以设置一些浏览器的属性,调用setJavaScriptEnabled()方法来让WebView支持javaScript脚本。

调用WebView的setWebViewClient()方法,并传入一个WebViewClinet实例。这段代码的作用是,当需要从一个网页跳转到另一个网页时,我们希望目标王爷仍然在当前WebView中显示,而不是打开浏览器。

WebView的loadUrl()方法将网址传入,就可以展示网页的内容,这里就让我们来看一看百度的首页。

由于本程序使用了网络功能,所以需要申请权限

2使用HTTP协议访问网络

  • HTTP 协议基础:客户端发请求,服务器返回数据,客户端解析处理,浏览器(含 WebView )依此工作。
  • WebView 示例:向百度服务器发 HTTP 请求,服务器返回百度首页 HTML 代码,WebView 调用手机浏览器内核解析展示。
  • WebView 特点与不足:后台处理发请求、收响应、解析数据、展示页面,因封装好,难直观看到 HTTP 协议工作过程,故需手动发请求深入理解 。

2.1使用HttpURLConnection

  1. 获取 HttpURLConnection 实例:通过 new URL() 传入目标网络地址创建 URL 对象,再调用 openConnection() 方法并强转为 HttpURLConnection 类型,得到其实例 。

    URL url = new URL("http://www.baidu.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    
  2. 设置 HTTP 请求方法:得到实例后,可用 setRequestMethod() 设置,常用 GET(从服务器获取数据 )和 POST(向服务器提交数据 )。

    connection.setRequestMethod("GET");
    
  3. 定制连接参数:可通过 setConnectTimeout()(设置连接超时 )、setReadTimeout()(设置读取超时 )等方法,依据实际需求定制。

    connection.setConnectTimeout(8000);
    connection.setReadTimeout(8000);
    
  4. 获取与处理服务器响应:调用 getInputStream() 获取服务器返回的输入流,后续需读取流中数据;操作完成后,用 disconnect() 关闭 HTTP 连接 。

    InputStream in = connection.getInputStream();
    connection.disconnect();
    

示例:新建一个NetWorkTest项目

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/send_request"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="发送请求" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/response_text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </ScrollView>

</LinearLayout>

package com.example.networktest;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity implements View

        .OnClickListener {
    TextView responseText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        View button = findViewById(R.id.send_request);
        responseText = findViewById(R.id.response_text);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.send_request) {
            sendRequestWithHttpURLConnection();
        }
    }
    private void sendRequestWithHttpURLConnection(){
        //开启线程来发起网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try{
                    URL url = new URL("https://www.baidu.com");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream in = connection.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while((line = reader.readLine()) != null){
                        response.append(line);
                    }
                    showResponse(response.toString());
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                   
                    if (reader != null){
                        try{
                            reader.close();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if (connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //在UI线程中显示响应内容
                responseText.setText(response);
            }
        });
    }
}

请求成功 在这里插入图片描述

可以成功看到服务器返回给我们的HTML代码。

提交数据也很简单,只需要将Http请求的方法改成POST,并在获取输入流之前把要提交的数据写出即可。注意每条数据都要以键值对的形式存在,数据和数据之间用&隔开,比如我们想要向服务器提交用户名和密码,就可以

connection.setRequestMethod("POST");
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeBytes("username = admin&password = 123456");

2.2使用OkHttp

现在时广大Android开发者的首选网络通信库。

在使用OKHttp之前需要在项目中添加OkHttp库的依赖。编辑app/build.gradle在dependencies闭包下添加

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:24.2.1'
    testImplementation 'junit:junit:4.12'
    implementation 'com.squareup.okhttp3:okhttp:3.4.1'

添加上述依赖自动下载两个库一个OkHttp,一个是Okio库,后者是前者通信的基础。

  1. OkHttp 基本使用流程

    • 创建客户端实例:通过 new OkHttpClient() 创建 OkHttpClient 实例,作为发起请求的客户端。

    • OkHttpClient client = new OkHttpClient();
      
    • 构建请求对象(Request):利用 Request.Builder 构建 Request 对象,可通过 url() 方法设置目标网络地址,若为 POST 请求,还需构建 RequestBody 存放参数,并用 post() 方法传入。

    • Request request = new Request.Builder()
             .url("http://www.baidu.com")
             .build();
      
    • 发起请求并获取响应:调用 OkHttpClientnewCall() 方法创建 Call 对象,再调用 execute() 发送请求,获取 Response 响应对象,从响应对象中可提取服务器返回数据。

    • Response response = client.newCall(request).execute();
      String responseData = response.body().string();
      
  2. GET 请求关键步骤:构建 Request 时用 url() 设地址,无需额外参数体,直接发起请求获取响应。

  3. POST 请求关键步骤:先通过 FormBody.Builder 构建 RequestBody 存放参数(如用户名、密码 ),再在 Request.Builder 中用 post() 方法传入该 RequestBody ,之后流程同 GET 请求。

    // 构建请求参数体
    RequestBody requestBody = new FormBody.Builder()
           .add("username", "admin")
           .add("password", "123456")
           .build();
    // 构建包含 POST 参数的请求
    Request request = new Request.Builder()
           .url("http://www.baidu.com")
           .post(requestBody)
           .build();
    

直接在前面的项目上做修改

package com.example.networktest;

import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okio.Okio;

public class MainActivity extends AppCompatActivity implements View

        .OnClickListener {
    TextView responseText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        View button = findViewById(R.id.send_request);
        responseText = findViewById(R.id.response_text);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.send_request) {
            sendRquestWithOkHttp();
        }
    }

    private void sendRquestWithOkHttp() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try{
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("https://www.baidu.com")
                            .build();
                    Response response = client.newCall(request).execute();
                    String responseData = response.body().string();
                    showResponse(responseData);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private void sendRequestWithHttpURLConnection(){
        //开启线程来发起网络请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                BufferedReader reader = null;
                try{
                    URL url = new URL("https://www.baidu.com");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream in = connection.getInputStream();
                    reader = new BufferedReader(new InputStreamReader(in));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while((line = reader.readLine()) != null){
                        response.append(line);
                    }
                    showResponse(response.toString());
                }catch (Exception e){
                    e.printStackTrace();
                }finally {

                    if (reader != null){
                        try{
                            reader.close();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                    if (connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }

    private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //在UI线程中显示响应内容
                responseText.setText(response);
            }
        });
    }
}

这里并没有做太大的改动,添加一个sendRequestWithOkHttp()方法,用OkHttp 的方式来实现了之前的Http请求

在这里插入图片描述

同样得到结果。

3.Retrofit

准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。
原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装本质过程

App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之后由 OkHttp 完成后续的请求操作
在服务端返回数据之后,OkHttp 将原始的结果交给 Retrofit,Retrofit根据用户的需求对结果进行解析

使用介绍

步骤1:添加Retrofit库的依赖

compile 'com.squareup.retrofit2:retrofit:2.0.2'

步骤2:创建 接收服务器返回数据 的类
步骤3:创建 用于描述网络请求 的接口
步骤4:创建 Retrofit 实例
步骤5:创建 网络请求接口实例 并 配置网络请求参数
步骤6:发送网络请求(异步 / 同步)
步骤7:处理服务器返回的数据

学习URL整合规则

package com.example.networktest;

import java.util.List;

public class Translation1 {

    private String type;
    private int errorCode;
    private int elapsedTime;
    private List<List<TranslateResultBean>> translateResult;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public int getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(int errorCode) {
        this.errorCode = errorCode;
    }

    public int getElapsedTime() {
        return elapsedTime;
    }

    public void setElapsedTime(int elapsedTime) {
        this.elapsedTime = elapsedTime;
    }

    public List<List<TranslateResultBean>> getTranslateResult() {
        return translateResult;
    }

    public void setTranslateResult(List<List<TranslateResultBean>> translateResult) {
        this.translateResult = translateResult;
    }

    public static class TranslateResultBean {
        /**
         * src : merry me
         * tgt : 我快乐
         */

        public String src;
        public String tgt;

        public String getSrc() {
            return src;
        }

        public void setSrc(String src) {
            this.src = src;
        }

        public String getTgt() {
            return tgt;
        }

        public void setTgt(String tgt) {
            this.tgt = tgt;
        }
    }

}

package com.example.networktest;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface PostRequest_Interface {

    @POST("mtpe-individual/transText?aldtype=16047&ext_channel=Aldtype#/auto/zh")
    @FormUrlEncoded
    Call<Translation1> getCall(@Field("i") String targetSentence);
    //采用@Post表示Post方法进行请求(传入部分url地址)
    // 采用@FormUrlEncoded注解的原因:API规定采用请求格式x-www-form-urlencoded,即表单形式
    // 需要配合@Field 向服务器提交需要的字段
}

package com.example.networktest;

import static android.content.ContentValues.TAG;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;


import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class PostRequest extends AppCompatActivity implements View.OnClickListener {

    private Button button;

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

        button = findViewById(R.id.send_request);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.send_request) {
            request();
        }
    }

    public void request() {

        //步骤4:创建Retrofit对象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://fanyi.baidu.com/") // 设置 网络请求 Url
                .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
                .build();

        // 步骤5:创建 网络请求接口 的实例
        PostRequest_Interface request = retrofit.create(PostRequest_Interface.class);

        //对 发送请求 进行封装(设置需要翻译的内容)
        Call<Translation1> call = request.getCall("I love you");

        //步骤6:发送网络请求(异步)
        call.enqueue(new Callback<Translation1>() {

            //请求成功时回调
            @Override
            public void onResponse(Call<Translation1> call, Response<Translation1> response) {
                // 步骤7:处理返回的数据结果:输出翻译的内容

                Log.d(TAG, "onResponse: "+response.body().getTranslateResult().get(0).get(0).getTgt());
            }

            //请求失败时回调
            @Override
            public void onFailure(Call<Translation1> call, Throwable throwable) {
                Log.d(TAG, "onFailure: "+throwable.getMessage());
            }
        });
    }


}


网站公告

今日签到

点亮在社区的每一天
去签到