Volley 缓存机制的问题

Issues with Volley caching mechanism

我有一个每天发布新闻的网站。

现在,我发送 JsonArrayRequest 来检索和解析网站上发布的每条新闻的标题和摘要。解析后的项目然后用于填充 RecyclerView。

我遇到的问题是 volley 实现缓存的方式。

让我们来看看这个场景:安装、启动应用程序并填充 RecyclerView。用户阅读新闻而忘记了应用程序

稍后,用户启动应用并获取项目并填充 RecyclerView。

在第一次和第二次发布之间,网站上发布了新消息。但是在第二次启动时,这些新项目并没有显示出来。但是,如果用户手动转到应用程序设置并清除应用程序的缓存,然后重新启动,则会显示新项目。

你明白我的意思了吗?

虽然我不想禁用 Volley 缓存,但如何让它始终获取新项目?

编辑

MainActivity

public class MainActivity extends AppCompatActivity {

    private final String TAG = "MainActivity";



    //Creating a list of newss
    private List<NewsItems> mNewsItemsList;

    //Creating Views
    private RecyclerView recyclerView;
    private RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;
    private ProgressDialog mProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate called");

        //Initializing Views
        recyclerView = (RecyclerView) findViewById(R.id.news_recycler);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);


        //Initializing the newslist
        mNewsItemsList = new ArrayList<>();
        adapter = new NewsAdapter(mNewsItemsList, this);

        recyclerView.setAdapter(adapter);

        if (NetworkCheck.isAvailableAndConnected(this)) {

            //Calling method to get data
            getData();
        } else {
            //Codes for building Alert Dialog
            alertDialogBuilder.setPositiveButton(R.string.alert_retry, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    if (!NetworkCheck.isAvailableAndConnected(mContext)) {
                        alertDialogBuilder.show();
                    } else {
                        getData();
                    }

                }
            });
            alertDialogBuilder.setNegativeButton(R.string.alert_cancel, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();

                }
            });
            alertDialogBuilder.show();

        }


    }



    //This method will get data from the web api
    private void getData(){


        Log.d(TAG, "getData called");
        //Codes for Showing progress dialog

        //Creating a json request
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigNews.GET_URL + getNumber(),
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, "onResponse called");
                        //Dismissing the progress dialog
                        if (mProgressDialog != null) {
                            mProgressDialog.hide();
                        }
                   //calling method to parse json array
                        parseData(response);

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                });

        //Creating request queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);

        //Adding request to the queue
        requestQueue.add(jsonArrayRequest);

    }

    //This method will parse json data
    private void parseData(JSONArray array){
        Log.d(TAG, "Parsing array");

        for(int i = 0; i<array.length(); i++) {
            NewsItems newsItem = new NewsItems();
            JSONObject jsonObject = null;
            try {
                jsonObject = array.getJSONObject(i);
                newsItem.setNews_title(jsonObject.getString(ConfigNews.TAG_VIDEO_TITLE));
                newsItem.setNews_body(jsonObject.getString(ConfigNews.TAG_VIDEO_BODY));

            } catch (JSONException w) {
                w.printStackTrace();
            }
            mNewsItemsList.add(newsItem);


        }

        adapter.notifyItemRangeChanged(0, adapter.getItemCount());
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy called");
        if (mProgressDialog != null){
            mProgressDialog.dismiss();
            Log.d(TAG, "mProgress dialog dismissed");

        }
    }

}

选项 1) 删除缓存

在拨打电话之前,您可以通过 myDiskBasedCache.clear() 删除整个缓存或通过 myDiskBasedCache.remove(entryUrl)

删除特定条目

选项 2) 自定义 CacheParser(在请求中)

    @Override
protected Response<Bitmap> parseNetworkResponse(NetworkResponse response) {
    Response<Bitmap> resp = super.parseNetworkResponse(response);
    if(!resp.isSuccess()) {
        return resp;
    }
    long now = System.currentTimeMillis();
    Cache.Entry entry = resp.cacheEntry;
    if(entry == null) {

        entry = new Cache.Entry();
        entry.data = response.data;
        entry.responseHeaders = response.headers;
        entry.ttl = now + 60 * 60 * 1000;  //keeps cache for 1 hr
    }
    entry.softTtl = 0; // will always refresh

    return Response.success(resp.result, entry);
}

选项 3) 发送不缓存的请求

myRequest.setShouldCache(false);

选项 4) 使用自定义缓存实现

更新:

您的代码示例:

    //Creating a json request
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigNews.GET_URL + getNumber(),
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, "onResponse called");
                        //Dismissing the progress dialog
                        if (mProgressDialog != null) {
                            mProgressDialog.hide();
                        }
                   //calling method to parse json array
                        parseData(response);

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {

                    }
                }) {
 @Override
    protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) {
        Response<JSONArray> resp = super.parseNetworkResponse(response);
        if(!resp.isSuccess()) {
            return resp;
        }
        long now = System.currentTimeMillis();
        Cache.Entry entry = resp.cacheEntry;
        if(entry == null) {

            entry = new Cache.Entry();
            entry.data = response.data;
            entry.responseHeaders = response.headers;
            entry.ttl = now + 60 * 60 * 1000;  //keeps cache for 1 hr
        }
        entry.softTtl = 0; // will always refresh

        return Response.success(resp.result, entry);
    }
};

更新 2

Http 协议缓存 支持多种方式来定义客户端如何缓存响应以及何时更新它们。 Volley 将这些规则简化为:

  • entry.ttl(以毫秒为单位的生存时间)如果大于当前时间则可以使用缓存,否则需要重新请求

  • entry.softTtl(软时间以ms为单位:)如果大于当前时间 缓存是绝对有效的,不需要向服务器发出请求,否则仍然会发出新请求(即使 ttl 是好的),如果有变化,将传递新的响应。

    请注意,如果 ttl 有效而 softTtl 无效,您可以收到 2 个 onResponse 调用