You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中Retrofit调用本地API加载失败及RecyclerView报错问题

Retrofit调用本地API数据加载问题排查与解决

问题描述

在Android Studio中使用Retrofit实现简单API,从localhost读取数据。API在Postman中运行正常,但Retrofit实现时无法加载本地数据,同时出现两个RecyclerView相关错误:

  • RecyclerView报错:No adapter attached; skipping layout
  • 空指针异常:java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference(位于PoetryAdapters.java第50行)

更新代码后,API调用验证成功:response.isSuccessful()返回true,状态码为1,提示“record available”,但response.body().getPoetryData()返回null,导致无法加载数据,已排除网络问题,寻求问题原因及解决方案。

可能原因及解决方案

1. 数据模型与API返回格式不匹配

这是response.body().getPoetryData()返回null的最常见原因:

  • 核对API返回的JSON结构,确保PoetryData实体类的字段名、数据类型、嵌套层级与JSON完全对应,注意大小写差异。
  • 若JSON字段名与实体类字段名不一致,需添加@SerializedName注解做映射,示例:
@SerializedName("poetry_data")
private ArrayList<Poetry> poetryData;
  • 确认API返回的数组字段名是否与getPoetryData()对应的实体类字段名一致,比如API返回"poems"而实体类用poetryData,会导致无法解析数据。

2. RecyclerView初始化与适配问题

针对No adapter attached; skipping layout和空指针异常:

  • 提前初始化Adapter并绑定到RecyclerView,即使初始数据为空列表,避免布局渲染时无Adapter:
// MainActivity的onCreate方法中
ArrayList<Poetry> emptyList = new ArrayList<>();
poetryAdapter = new PoetryAdapters(emptyList);
recyclerView.setAdapter(poetryAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
  • 在PoetryAdapters中添加空数据判断,避免调用size()时触发空指针:
// PoetryAdapters的getItemCount方法
@Override
public int getItemCount() {
    return poetryList != null ? poetryList.size() : 0;
}

3. 本地API访问配置问题

虽已排除网络问题,仍需确认以下配置:

  • 替换localhost为电脑的局域网IP(如http://192.168.1.100:8080),Android模拟器可使用10.0.2.2访问主机API。
  • 确保AndroidManifest.xml添加了网络权限:
<uses-permission android:name="android.permission.INTERNET" />
  • Android 9及以上版本,若API使用http协议,需在res/xml/network_security_config.xml中配置允许明文流量:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">你的API域名/IP</domain>
    </domain-config>
</network-security-config>

并在AndroidManifest的application标签中引用该配置:

android:networkSecurityConfig="@xml/network_security_config"

4. Retrofit配置问题

检查ApiClient中的Gson转换器配置,确保能正确解析JSON:

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build();

若API返回的根节点是数组而非对象,需调整接口定义,示例:

// 直接返回Poetry数组的接口定义
@GET("poetry")
Call<ArrayList<Poetry>> getPoetryData();

相关代码示例

MainActivity.java关键代码

// 初始化RecyclerView
RecyclerView recyclerView = findViewById(R.id.recyclerView);
poetryAdapter = new PoetryAdapters(new ArrayList<>());
recyclerView.setAdapter(poetryAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));

// API调用逻辑
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<PoetryResponse> call = apiInterface.getPoetry();
call.enqueue(new Callback<PoetryResponse>() {
    @Override
    public void onResponse(Call<PoetryResponse> call, Response<PoetryResponse> response) {
        if (response.isSuccessful()) {
            PoetryResponse poetryResponse = response.body();
            if (poetryResponse != null && poetryResponse.getPoetryData() != null) {
                poetryAdapter.updateData(poetryResponse.getPoetryData());
            } else {
                // 处理数据为空的场景
            }
        } else {
            // 处理请求失败场景
        }
    }

    @Override
    public void onFailure(Call<PoetryResponse> call, Throwable t) {
        t.printStackTrace();
    }
});

PoetryAdapters.java关键代码

public class PoetryAdapters extends RecyclerView.Adapter<PoetryAdapters.ViewHolder> {
    private ArrayList<Poetry> poetryList;

    public PoetryAdapters(ArrayList<Poetry> poetryList) {
        this.poetryList = poetryList;
    }

    // 添加数据更新方法
    public void updateData(ArrayList<Poetry> newData) {
        this.poetryList = newData;
        notifyDataSetChanged();
    }

    @Override
    public int getItemCount() {
        return poetryList != null ? poetryList.size() : 0;
    }

    // ViewHolder及其他相关代码...
}

ApiClient.java代码

public class ApiClient {
    private static final String BASE_URL = "http://192.168.1.100:8080/api/"; // 替换为实际局域网IP
    private static Retrofit retrofit;

    public static Retrofit getApiClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

内容的提问来源于stack exchange,提问作者Sarmad Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:55:01