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

Android拉取服务端JSON更新后不显示,清缓存才生效如何解决

解决方案

核心问题原因

  • Volley默认开启HTTP响应缓存,未配置的情况下会优先返回缓存的旧数据,不会请求服务端最新内容
  • 每次拉取数据前未清空原有列表缓存,即便拿到新数据也会和旧数据叠加而非替换
  • 布局内置的下拉刷新组件未绑定逻辑,无法手动触发数据更新
  • Glide图片加载默认开启缓存,若服务端图片资源更新但链接不变,会继续展示旧图片

具体修改步骤

1. 配置Volley强制拉取最新数据,每次请求清空旧列表

首先在Home类中把Adapter和SwipeRefreshLayout声明为全局变量,修改请求逻辑关闭缓存、清空旧数据:

public class Home extends Fragment {
    private final String JSON_URL = "https://mywebsite.org/news/api.php";
    private JsonArrayRequest request ;
    private RequestQueue requestQueue ;
    private List<Anime> lstAnime ;
    private RecyclerView recyclerView ;
    ProgressBar loading;
    // 新增全局变量
    private RecyclerViewAdapter myadapter;
    private SwipeRefreshLayout swipeContainer;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.fragment_home, container, false);
        loading = root.findViewById(R.id.bar);
        loading.setMax(100);
        lstAnime = new ArrayList<>() ;
        recyclerView = root.findViewById(R.id.recyclerviewid);
        // 绑定下拉刷新组件
        swipeContainer = root.findViewById(R.id.swipeContainer);
        // 初始化RecyclerView和Adapter,只做一次
        initRecyclerView();
        // 绑定下拉刷新监听
        swipeContainer.setOnRefreshListener(() -> {
            jsonrequest();
        });
        // 设置刷新动画配色可选
        swipeContainer.setColorSchemeResources(android.R.color.holo_blue_bright,
                android.R.color.holo_green_light,
                android.R.color.holo_orange_light,
                android.R.color.holo_red_light);
        jsonrequest();
        return root;
    }
    
    // 新增初始化RecyclerView方法,只调用一次
    private void initRecyclerView(){
        myadapter = new RecyclerViewAdapter(getActivity(),lstAnime);
        GridLayoutManager manager = new GridLayoutManager(getActivity(), 2);
        manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                if (position == 0 || position == 9) {
                    return 2;
                }
                return 1;}
        });
        recyclerView.setItemAnimator(null);
        recyclerView.setHasFixedSize(true);
        recyclerView.setAdapter(myadapter);
        recyclerView.setLayoutManager(manager);
    }

    private void jsonrequest() {
        // 请求前先清空旧数据
        lstAnime.clear();
        request = new JsonArrayRequest(JSON_URL, new Response.Listener<JSONArray>() {
            @Override
            public void onResponse(JSONArray response) {
                loading.setVisibility(View.GONE);
                // 关闭下拉刷新动画
                if(swipeContainer.isRefreshing()){
                    swipeContainer.setRefreshing(false);
                }
                JSONObject jsonObject  = null ;
                for (int i = 0 ; i < response.length(); i++ ) {
                    try {
                        jsonObject = response.getJSONObject(i) ;
                        Anime anime = new Anime() ;
                        anime.setName(jsonObject.getString("title"));
                        anime.setDescription(jsonObject.getString("description"));
                        anime.setDate(jsonObject.getString("date"));
                        anime.setCategorie(jsonObject.getString("category"));
                        anime.setAuthor(jsonObject.getString("admin"));
                        anime.setImage_url(jsonObject.getString("thumbnail"));
                        lstAnime.add(anime);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                // 通知Adapter数据更新
                myadapter.notifyDataSetChanged();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                // 错误时也要关闭刷新动画
                loading.setVisibility(View.GONE);
                if(swipeContainer.isRefreshing()){
                    swipeContainer.setRefreshing(false);
                }
                if (error instanceof TimeoutError || error instanceof NoConnectionError) {
                    Toast.makeText(getActivity(), "超时,请检查网络连接",
                            Toast.LENGTH_LONG).show();
                } else if (error instanceof AuthFailureError) {
                    Toast.makeText(getActivity(), "获取数据失败",
                            Toast.LENGTH_LONG).show();
                } else if (error instanceof ServerError) {
                    Toast.makeText(getActivity(), "服务器维护中",
                            Toast.LENGTH_LONG).show();
                } else if (error instanceof NetworkError) {
                    Toast.makeText(getActivity(), "网络无响应",
                            Toast.LENGTH_LONG).show();
                } else if (error instanceof ParseError) {
                    Toast.makeText(getActivity(), "请重新加载",
                            Toast.LENGTH_LONG).show();
                }
            }
        });
        // 核心配置:关闭Volley缓存,强制拉取服务端最新数据
        request.setShouldCache(false);
        requestQueue = Volley.newRequestQueue(getActivity());
        requestQueue.add(request);
    }
    // 其余原有代码保持不变
}

2. 配置Glide缓存策略适配图片更新

如果服务端图片资源更新但链接不变,可修改RecyclerViewAdapter中Glide的加载配置,跳过缓存(如果图片链接会随资源更新而变化则不需要改):

// 替换原有的Glide加载代码
Glide.with(mContext)
    .load(mData.get(position).getImage_url())
    .apply(option)
    .skipMemoryCache(true) // 跳过内存缓存
    .diskCacheStrategy(DiskCacheStrategy.NONE) // 跳过磁盘缓存
    .into(holder.thumbnail);

如果不想完全禁用缓存影响性能,可在服务端返回的图片数据中新增版本号参数,每次图片更新时修改版本号,Glide会自动识别为新资源加载。

3. 可选:实现自动定时刷新

如果需要不需要手动操作的实时更新,可在Fragment可见时开启定时任务,每隔固定时间(比如5分钟)自动调用jsonrequest()拉取最新数据,Fragment不可见时关闭定时任务避免浪费资源。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:24:05