android OkHttpClient.newCall(request).enqueue()请求与返回值怎样在Activity里面调用,第一次调用为null,问题记录。

  1. 问题分析

    • 当在 Activity 中使用OkHttpClient.newCall(request).enqueue()进行网络请求时,由于这是一个异步请求,它不会阻塞当前线程,所以如果在请求还未完成时就尝试获取返回值,就会得到null
  2. 解决方案 - 使用回调接口

    • 定义接口
      • 首先,在 Activity 类中定义一个接口来处理网络请求的结果。例如:
public interface NetworkCallback {
    void onSuccess(String response);
    void onFailure(Exception e);
}

  • 在 Activity 中进行网络请求并使用接口处理结果
    • 假设在MainActivity中进行网络请求,示例代码如下:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {

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

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
               .url("https://example.com/api/data")
               .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 在主线程中更新UI,需要使用runOnUiThread方法
                runOnUiThread(() -> {
                    // 假设存在一个TextView来显示错误信息
                    // TextView errorTextView = findViewById(R.id.error_text_view);
                    // errorTextView.setText("网络请求失败:" + e.getMessage());
                    ((NetworkCallback) MainActivity.this).onFailure(e);
                });
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    final String responseData = response.body().string();
                    // 在主线程中更新UI,需要使用runOnUiThread方法
                    runOnUiThread(() -> {
                        // 假设存在一个TextView来显示返回的数据
                        // TextView resultTextView = findViewById(R.id.result_text_view);
                        // resultTextView.setText("网络请求成功,返回数据:" + responseData);
                        ((NetworkCallback) MainActivity.this).onSuccess(responseData);
                    });
                } else {
                    final String errorMessage = "网络请求失败,状态码:" + response.code();
                    // 在主线程中更新UI,需要使用runOnUiThread方法
                    runOnUiThread(() -> {
                        // 假设存在一个TextView来显示错误信息
                        // TextView errorTextView = findViewById(R.id.error_text_view);
                        // errorTextView.setText(errorMessage);
                        ((NetworkCallback) MainActivity.this).onFailure(new IOException(errorMessage));
                    });
                }
            }
        });
    }
}

在上述代码中:

  • 首先创建了OkHttpClientRequest对象,然后使用client.newCall(request).enqueue()进行异步网络请求。
  • onFailure方法中,当网络请求失败时,通过runOnUiThread方法在主线程中更新 UI 或者调用定义的接口方法onFailure来通知调用者请求失败。
  • onResponse方法中,当网络请求成功且响应状态码为成功时,获取响应体数据并转换为字符串,然后同样通过runOnUiThread方法在主线程中更新 UI 或者调用接口方法onSuccess来通知调用者请求成功并传递返回的数据。如果响应状态码不是成功状态,则按照请求失败的方式处理,传递相应的错误信息。
  1. 更好的实践 - 抽象网络请求层
    • 为了使代码更加模块化和易于维护,可以将网络请求部分封装到一个单独的类中。例如,创建一个NetworkManager类:
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;

public class NetworkManager {
    private OkHttpClient client;

    public NetworkManager() {
        client = new OkHttpClient();
    }

    public void sendRequest(Request request, final NetworkCallback callback) {
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callback.onFailure(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    final String responseData = response.body().string();
                    callback.onSuccess(responseData);
                } else {
                    final String errorMessage = "网络请求失败,状态码:" + response.code();
                    callback.onFailure(new IOException(errorMessage));
                }
            }
        });
    }
}

  • 然后在MainActivity中使用这个NetworkManager类:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import okhttp3.Request;
import okhttp3.Request.Builder;

public class MainActivity extends AppCompatActivity implements NetworkCallback {

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

        NetworkManager networkManager = new NetworkManager();
        Request request = new Builder()
               .url("https://example.com/api/data")
               .build();
        networkManager.sendRequest(request, this);
    }

    @Override
    public void onSuccess(String response) {
        // 在这里处理网络请求成功后的逻辑,如更新UI
        // 假设存在一个TextView来显示返回的数据
        // TextView resultTextView = findViewById(R.id.result_text_view);
        // resultTextView.setText("网络请求成功,返回数据:" + response);
    }

    @Override
    public void onFailure(Exception e) {
        // 在这里处理网络请求失败后的逻辑,如显示错误信息
        // 假设存在一个TextView来显示错误信息
        // TextView errorTextView = findViewById(R.id.error_text_view);
        // errorTextView.setText("网络请求失败:" + e.getMessage());
    }
}

通过这种方式,将网络请求的逻辑封装在NetworkManager类中,MainActivity只需要实现NetworkCallback接口并处理请求成功和失败的情况,使代码结构更加清晰,易于维护和扩展。同时,避免了在 Activity 中直接处理异步请求带来的返回值获取问题,通过接口回调的方式在请求完成后接收结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码熊崽的编程森林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值