package com.example.kucun2.entity.data;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.example.kucun2.entity.Information;
import com.example.kucun2.entity.User;
import com.example.kucun2.function.MyAppFunction;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import okhttp3.*;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
/**
* 重构版API客户端 - 更灵活的类型处理
* 主要改进:
* 1. 分离请求参数类型和响应类型
* 2. 支持多种请求方法(GET/POST/PUT/DELETE)
* 3. 支持表单和JSON两种请求格式
* 4. 自动推导响应类型
* 5. 统一的请求执行流程
*/
public class ApiClient {
private static final Gson gson = GsonFactory.createGson();
private static final String TAG = "ApiClient";
private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
private static final int MAX_RETRY = 3;
private static final Handler MAIN_HANDLER = new Handler(Looper.getMainLooper());
// ====================== 核心请求方法 ======================
/**
* 执行API请求(核心方法)
* @param request 构建好的OkHttp请求
* @param responseType 期望的响应类型
* @param callback 回调接口
* @param <R> 响应数据类型
*/
public static <R> void executeRequest(Request request,
Type responseType,
ApiCallback<R> callback) {
OkHttpClient client = MyAppFunction.getClient();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handleFailure(call, e, callback, 0);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
handleResponse(response, responseType, callback);
}
});
}
// ====================== 请求构建方法 ======================
/**
* 构建JSON请求
* @param url API地址
* @param method 请求方法("POST", "PUT", "DELETE")
* @param requestData 请求数据对象
* @return 构建好的Request对象
*/
public static Request buildJsonRequest(String url, String method, Object requestData) {
String jsonRequest = ReflectionJsonUtils.toJson(requestData);
Log.d(TAG, method + " URL: " + url);
Log.d(TAG, "请求数据: " + jsonRequest);
RequestBody body = RequestBody.create(JSON, jsonRequest);
return new Request.Builder()
.url(url)
.method(method, body)
.build();
}
/**
* 构建表单请求
* @param url API地址
* @param method 请求方法
* @param formData 表单数据
* @return 构建好的Request对象
*/
public static Request buildFormRequest(String url, String method, Map<String, String> formData) {
FormBody.Builder builder = new FormBody.Builder();
for (Map.Entry<String, String> entry : formData.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
Log.d(TAG, method + " URL: " + url);
Log.d(TAG, "表单数据: " + formData);
return new Request.Builder()
.url(url)
.method(method, builder.build())
.build();
}
// ====================== 响应处理方法 ======================
private static <R> void handleResponse(Response response,
Type responseType,
ApiCallback<R> callback) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) {
String error = "HTTP " + response.code() + ": " + response.message();
Log.e(TAG, error);
notifyError(callback, response.code(), error);
return;
}
String jsonResponse = responseBody.string();
Log.d(TAG, "服务器响应: " + jsonResponse);
// 解析服务端的Information包装
Information<R> wrapper = gson.fromJson(jsonResponse, responseType);
if (wrapper != null && wrapper.getStatus() == 200) {
notifySuccess(callback, wrapper.getData());
} else {
String errorMsg = wrapper != null ?
"服务端错误: " + wrapper.getStatus() + " - " + wrapper.getText() :
"无效的响应格式";
Log.e(TAG, errorMsg);
notifyError(callback,
wrapper != null ? wrapper.getStatus() : -1,
errorMsg);
}
} catch (Exception e) {
Log.e(TAG, "响应处理异常: " + e.getMessage());
notifyError(callback, -2, "数据处理异常: " + e.getMessage());
}
}
// ====================== 失败处理与重试 ======================
private static <R> void handleFailure(Call call,
IOException e,
ApiCallback<R> callback,
int retryCount) {
if (retryCount < MAX_RETRY) {
Log.w(TAG, "请求失败,第" + (retryCount + 1) + "次重试: " + e.getMessage());
MAIN_HANDLER.postDelayed(() -> {
call.clone().enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
handleFailure(call, e, callback, retryCount + 1);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
handleResponse(response, getResponseType(callback), callback);
}
});
}, 2000);
} else {
Log.e(TAG, "最终请求失败: " + e.getMessage());
notifyError(callback, -1, "网络请求失败: " + e.getMessage());
}
}
// ====================== 类型处理工具 ======================
/**
* 获取响应类型(通过回调接口的泛型参数)
*/
private static <R> Type getResponseType(ApiCallback<R> callback) {
if (callback == null) {
return new TypeToken<Information<Object>>(){}.getType();
}
// 尝试获取泛型类型
Type[] genericInterfaces = callback.getClass().getGenericInterfaces();
for (Type type : genericInterfaces) {
if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType) type;
if (pType.getRawType().equals(ApiCallback.class)) {
Type dataType = pType.getActualTypeArguments()[0];
return TypeToken.getParameterized(Information.class, dataType).getType();
}
}
}
// 默认返回Object类型
Log.w(TAG, "无法确定响应类型,使用默认Object类型");
return new TypeToken<Information<Object>>(){}.getType();
}
// ====================== 回调通知方法 ======================
private static <R> void notifySuccess(ApiCallback<R> callback, R data) {
if (callback != null) {
MAIN_HANDLER.post(() -> callback.onSuccess(data));
}
}
private static <R> void notifyError(ApiCallback<R> callback, int code, String error) {
if (callback != null) {
MAIN_HANDLER.post(() -> callback.onError(code, error));
}
}
// ====================== 专用API方法 ======================
/**
* 执行JSON API请求
* @param url API地址
* @param method 请求方法
* @param requestData 请求数据
* @param callback 回调接口
* @param <T> 请求数据类型
* @param <R> 响应数据类型
*/
public static <T, R> void jsonRequest(String url,
String method,
T requestData,
ApiCallback<R> callback) {
Request request = buildJsonRequest(url, method, requestData);
executeRequest(request, getResponseType(callback), callback);
}
/**
* 执行表单API请求
* @param url API地址
* @param method 请求方法
* @param formData 表单数据
* @param callback 回调接口
* @param <R> 响应数据类型
*/
public static <R> void formRequest(String url,
String method,
Map<String, String> formData,
ApiCallback<R> callback) {
Request request = buildFormRequest(url, method, formData);
executeRequest(request, getResponseType(callback), callback);
}
// ====================== 便捷方法 ======================
public static <T, R> void postJson(String url, T data, ApiCallback<R> callback) {
jsonRequest(url, "POST", data, callback);
}
public static <T, R> void putJson(String url, T data, ApiCallback<R> callback) {
jsonRequest(url, "PUT", data, callback);
}
public static <T, R> void deleteJson(String url, T data, ApiCallback<R> callback) {
jsonRequest(url, "DELETE", data, callback);
}
public static <R> void get(String url, ApiCallback<R> callback) {
Request request = new Request.Builder().url(url).get().build();
executeRequest(request, getResponseType(callback), callback);
}
// ====================== 登录专用方法 ======================
public static void login(String username, String password, LoginCallback callback) {
String url = MyAppFunction.getApiUrl("url_login");
Log.d(TAG, "login: " + url);
formRequest(url, "POST", Map.of(
"andy", username,
"pass", password
), new ApiCallback<User>(User.class) {
@Override
public void onSuccess(User user) {
if (callback != null) callback.onSuccess(user);
}
@Override
public void onError(int statusCode, String error) {
if (callback != null) callback.onFailure(error);
}
});
}
// ====================== 回调接口定义 ======================
public static abstract class ApiCallback<T> {
private final Type responseType;
public Type getResponseType() {
return responseType;
}
protected ApiCallback(Class<T> responseType) {
this.responseType = responseType;
}
public abstract void onSuccess(T data);
protected abstract void onError(int statusCode, String error);
}
public interface LoginCallback {
void onSuccess(User user);
void onFailure(String error);
}
}
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.kucun2.entity.User