请注意,如果Web服务支持缓存输出,则不必使用下面的
CacheRequest
,因为
Volley
会自动缓存。
对于您的问题,我在
parseCacheHeaders
中使用了一些代码(参考了@oleksandr_yefremov的代码)。以下代码已经经过测试。当然,也可以用于
JsonArrayRequest
。希望这有帮助!
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(0, mUrl, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
mTextView.setText(response.toString(5));
} catch (JSONException e) {
mTextView.setText(e.toString());
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
}) {
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
final long cacheHitButRefreshed = 3 * 60 * 1000;
final long cacheExpired = 24 * 60 * 60 * 1000;
long now = System.currentTimeMillis();
final long softExpire = now + cacheHitButRefreshed;
final long ttl = now + cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = softExpire;
cacheEntry.ttl = ttl;
String headerValue;
headerValue = response.headers.get("Date");
if (headerValue != null) {
cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
headerValue = response.headers.get("Last-Modified");
if (headerValue != null) {
cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
cacheEntry.responseHeaders = response.headers;
final String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString), cacheEntry);
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(JSONObject response) {
super.deliverResponse(response);
}
@Override
public void deliverError(VolleyError error) {
super.deliverError(error);
}
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
};
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
更新:
如果您需要一个基类,请参考以下代码:
public class CacheRequest extends Request<NetworkResponse> {
private final Response.Listener<NetworkResponse> mListener;
private final Response.ErrorListener mErrorListener;
public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
}
@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
final long cacheHitButRefreshed = 3 * 60 * 1000;
final long cacheExpired = 24 * 60 * 60 * 1000;
long now = System.currentTimeMillis();
final long softExpire = now + cacheHitButRefreshed;
final long ttl = now + cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = softExpire;
cacheEntry.ttl = ttl;
String headerValue;
headerValue = response.headers.get("Date");
if (headerValue != null) {
cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
headerValue = response.headers.get("Last-Modified");
if (headerValue != null) {
cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
cacheEntry.responseHeaders = response.headers;
return Response.success(response, cacheEntry);
}
@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
}
然后在MainActivity中,您可以这样调用:
CacheRequest cacheRequest = new CacheRequest(0, mUrl, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
try {
final String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
JSONObject jsonObject = new JSONObject(jsonString);
mTextView.setText(jsonObject.toString(5));
} catch (UnsupportedEncodingException | JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.toString());
}
});
MySingleton.getInstance(this).addToRequestQueue(cacheRequest);
完整源代码更新:
MainActivity.java:
package com.example.cachevolley;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.Cache;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.Volley;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
public class MainActivity extends AppCompatActivity {
private final Context mContext = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView) findViewById(R.id.textView);
RequestQueue queue = Volley.newRequestQueue(this);
String url = "http://192.168.0.100/apitest";
CacheRequest cacheRequest = new CacheRequest(0, url, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
try {
final String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
JSONObject jsonObject = new JSONObject(jsonString);
textView.setText(jsonObject.toString(5));
Toast.makeText(mContext, "onResponse:\n\n" + jsonObject.toString(), Toast.LENGTH_SHORT).show();
} catch (UnsupportedEncodingException | JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mContext, "onErrorResponse:\n\n" + error.toString(), Toast.LENGTH_SHORT).show();
}
});
queue.add(cacheRequest);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class CacheRequest extends Request<NetworkResponse> {
private final Response.Listener<NetworkResponse> mListener;
private final Response.ErrorListener mErrorListener;
public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
}
@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
final long cacheHitButRefreshed = 3 * 60 * 1000;
final long cacheExpired = 24 * 60 * 60 * 1000;
long now = System.currentTimeMillis();
final long softExpire = now + cacheHitButRefreshed;
final long ttl = now + cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = softExpire;
cacheEntry.ttl = ttl;
String headerValue;
headerValue = response.headers.get("Date");
if (headerValue != null) {
cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
headerValue = response.headers.get("Last-Modified");
if (headerValue != null) {
cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
}
cacheEntry.responseHeaders = response.headers;
return Response.success(response, cacheEntry);
}
@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
}
}
清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.cachevolley" >
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
</RelativeLayout>
protected Response<JSONObject>
,比如将其作为一个Volley
单例类。我希望在所有从服务器请求数据的类中都能使用这个定义好的缓存方法。 - user4790312parseNetworkResponse
方法。所有其他请求/类都将使用/扩展基类。 - BNK602197949-1512839413
。你同意它比仅有的602197949
更加“独特”吗? :) 。在Javadoc中,@return A pseudo-unique filename
。 - BNKcacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
未定义的人,请确保您使用了最新版本的Volley,并检查是否在任何地方都没有旧的Volleycompile files('libs/httpmime-4.3.jar')
。如果有,请将其删除并在gradle中替换为`dependencies { ... compile 'com.android.volley:volley:1.0.0' }`
- Cedriga