my below sample code work fine without any some problem, this sample code can cache received data from url and using that when device doesnt have any internet connection.
but this code have a big deficiency, it is when device have internet connection i cant recache and get newest data from internet and recache again until device doesnt have connection, some data can be image or json array or json object
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.1.2/test";
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));
Log.e('OutPut',jsonObject.toString());
} 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) {
// Inflate the menu; this adds items to the action bar if it is present.
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; // in 3 minutes cache will be hit, but also refreshed on background
final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
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);
}
}
}
It will cache only once because onCreate method is called once the app created..
most suitable solution would be this:
You need to have a Service which uses AlarmManager for, say, every 5 minutes to trigger itself. And in this service you can cache the newest data in the background, of course for smaller time unit, more battery will be consumed.
update for cache resizing
RequestQueue volleyQueue = Volley.newRequestQueue(this);
DiskBasedCache cache = new DiskBasedCache(getCacheDir(), 16 * 1024 * 1024);
volleyQueue = new RequestQueue(cache, new BasicNetwork(new HurlStack()));
volleyQueue.start();
according to that discussion volley's cache can be manipulated, but when it gets full, automatically replaces new data with the old one so, cache size is not the focus right now.
update for cache cleaning
mahdi, according to official link of google volley's Cache class, there is a method called invalidate(), which invalidates the cached data, and next time volley checks if data was valid and update it.
you can appereantly delete cache for every 30 minutes according to this discussion:
serverDate: AppController.getInstance().getRequestQueue().getCache().get(url).serverDate
getMinutesDifference is method calculates time passed, can be found on reference link.
Calendar calendar = Calendar.getInstance();
long serverDate = AppController.getInstance().getRequestQueue().getCache().get(url).serverDate;
if(getMinutesDifference(serverDate, calendar.getTimeInMillis()) >=30)
{
AppController.getInstance().getRequestQueue().getCache().invalidate(url, true);
}
You can first check your Internet connection, if you have connection you can clear the cache and reload
ConnectivityManager connMgr = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
MySocialMediaSingleton.getInstance(getContext()).getRequestQueue().getCache().invalidate("http://server/json.php?page=1", true);
}
//Calling again method to get data to fetch data
getData();
Related
I am trying to implement pagination in recyclerview to load more chat messages when the user scrolls to top , this is achieved by sending the last message time i.e coversations[0] time to the API , but when the new list is added the old List gets repeated many times . I think this is because i am not updating the time properly , What is the correct way to achieve this?
This is the code i am using, first time i am setting the flag to false and time as empty.
getConvoData(k, " ", "", false);
private String last_msg_time = " ";
private Boolean flag = false;
rv_convo.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!recyclerView.canScrollVertically(-1)) {
if (conversations != null) {
String time = last_msg_time;
getConvoData(k, " ", time, true);
}
}
}
});
this is the method for fetching conversation Data
private void getConvoData(final String k, final String new_message, final String last_time, final boolean flag) {
final String token1 = Global.shared().tb_token;
final String url = "https://app.aer.media/v2/message_router/_getChat";
final JSONObject jsonBody = new JSONObject();
final ProgressDialog progressDialog = new ProgressDialog(this);
final String mRequestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
final JSONObject data = jObj.getJSONObject("data");
conversations = data.getJSONArray("conversation");
JSONObject for_chat = data.getJSONObject("for_chat");
JSONArray jsonArr_chat = new JSONArray();
jsonArr_chat.put(for_chat);
params = (RelativeLayout.LayoutParams) rv_convo.getLayoutParams();
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
if (!flag) {
convobeans = gson.fromJson(conversations.toString(), convType);
last_msg_time = conversations.getJSONObject(0).getString("time");
Log.d("OldList", convobeans.toString());
adapter = new ChatDetailsAdapter(forChatBeen, convobeans, ChatDetailsActivity.this, forChatBeansList, image, name, initials, new_message, bitmap);
// Collections.reverse(convobeans);
rv_convo.setAdapter(adapter);
rv_convo.smoothScrollToPosition( rv_convo.getAdapter().getItemCount() - 1);
adapter.notifyDataSetChanged();
rv_convo.setNestedScrollingEnabled(true);
} else {
newConvo = gson.fromJson(conversations.toString(), convType);
last_msg_time = conversations.getJSONObject(0).getString("time");
if (newConvo != null && newConvo.size() > 0) {
Log.d("newList", newConvo.toString());
convobeans.addAll(0, newConvo);
adapter.notifyItemChanged(0, newConvo.size());
}
}
}
}
}
Depending on the flag I am updating the list and updating the time as well but the list gets repeated in the RecyclerView due to the previous time being passed , how do I update the time optimally and fetch the new list each time?
This code is used to fetch the data when the user scroll down in a recylerview. Just analyze this code you will get the basic idea.
rvCategory.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) {
visibleItemCount = mLinearLayoutManager.getChildCount();
totalItemCount = mLinearLayoutManager.getItemCount();
pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
fetchData();
}
}
}
}
});
Function FetchData()
private void fetchData() {
String url = EndPoints.location + "getMobileData.php?lastData=" + lastData;
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
lastData = response.getString("last");
JSONArray jArray = response.getJSONArray("response");
if (jArray.length() == 0) {
//Empty condition
} else {
for (int i = 0; i < jArray.length(); i++) {
//Append the chat with the Dataobject of your modelAnd swap the recylerview view with new data
//Example
}
adapter.swap(rvHomeModel.createHomeList(DataPathsHome, true));
}
} catch (JSONException e) {
e.printStackTrace();
}
loading = true;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
loading = true;
Toast.makeText(CategoryView.this, "No internet connection", Toast.LENGTH_LONG).show();
}
});
// Add a request (in this example, called stringRequest) to your RequestQueue.
MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);
}
Create a function called swap in your adapter class that accept the new dataset
public void swap(List<rvHomeModel> list) {
//Check your previouse dataset used in adapter is empty or not
if (rvHomeModels!= null) {
rvHomeModels.clear();
rvHomeModels.addAll(list);
} else {
rvHomeModels = list;
}
notifyDataSetChanged();
}
At server
1. Get the previous value
2. Do the database operation and get the chats id < of previous
2. Create a JSON Object contain
{
last:last_chat_id,
response:{
//Your chat
}
}
This is not a perfect solution for this question. But you will get the basic idea about what you are looking for.
I have an IntentService which is supposed to send thousands of Volley requests to my server. It works fine and is very fast. I create my requests based on a Cursor I get from a ContentProvider (getContentResolver()).
I do however want to avoid making requests for items which are already available client-side. I get this list of items by calling
List<List> savedLyrics = DatabaseHelper.getInstance(this).listMetadata();
If that list is empty, it works fine. However, if it's not - then when this method
savedLyrics.contains(Arrays.asList(artist, title))
gets called, it seems to really slow things down.
public class BatchDownloaderService extends IntentService implements Response.Listener<String>, Response.ErrorListener {
private int total = 0;
private int count = 0;
private int successCount = 0;
private RequestQueue requestQueue;
private OkHttpClient client = null;
public BatchDownloaderService() {
super("Batch Downloader Service");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
onHandleIntent(intent);
return START_NOT_STICKY;
}
#Override
protected void onHandleIntent(Intent intent) {
if (client == null)
getClient();
Uri content = intent.getExtras().getParcelable("uri");
List<List> savedLyrics = DatabaseHelper.getInstance(this).listMetadata();
Cursor cursor = /* Get My Cursor */;
if (cursor == null)
return;
total = cursor.getCount();
updateProgress();
final Cache cache = new DiskBasedCache(getCacheDir(), 1024*1024);
final Network network = new BasicNetwork(new OkHttp3Stack(client));
requestQueue = new RequestQueue(cache, network, 8);
requestQueue.start();
while (cursor.moveToNext()) {
String artist = cursor.getString(0);
String title = cursor.getString(1);
if (artist == null || title == null || artist.isEmpty() || title.isEmpty() || savedLyrics.contains(Arrays.asList(artist, title))) {
// If the local database already contains this item (or if null), skip the request
updateProgress();
continue;
}
try {
Request request = QuickLyricAPI.getVolleyRequest(lrc, this, this, artist, title);
requestQueue.add(request);
} catch (Exception e) {
// Stuff
}
}
cursor.close();
}
private void updateProgress() {
/* Update the progressbar in the notification */
}
#Override
public void onErrorResponse(VolleyError error) {
updateProgress();
error.printStackTrace();
}
#Override
public void onResponse(String response) {
/* Stuff */
updateProgress();
}
private void getClient() {
/* Stuff */
}
}
If I comment out the call to .contains(), then I see no difference with the list being empty and everything is smooth.
I tried to replace the list with a TreeSet() with a comparator, it didn't make it faster. I tried to use String arrays instead of Lists, it didn't make it faster. I also tried using a Countdownlatch to make it so that onHandleIntent() doesn't finish before all the requests were done. Didn't work.
How can an IntentService slow down the whole device and even crash my SystemUI like this? I thought it was running in its own thread.
How can checking a list (2500 items in this case) be so expensive?
Testing this on a Nextbit Robin with 7.0
Cheers
I have a website which publishes news on daily basis.
Now, I'm sending a JsonArrayRequest to retrieve and parse the title and summary of each news published on the website. The parsed items are then used to populate RecyclerView.
The problem I'm having is the way volley implements caching .
Let's take this scenario: the app is installed, launched and the RecyclerView is populated. The user reads the news and forgets about the app
Later, the user launches the app and the items are fetched and RecyclerView is populated.
Between the first and the second launch, new news are published on the website. But in the second launch, these new items are not displayed. However, if the user manually go to app settings and clear cache of the app, and relaunch, the new items are displayed.
You get my point?
While I don't want to disable Volley caching, how do I make it to always fetch new items?
EDIT
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");
}
}
}
Option 1) Delete Cache
before you make a call you can delete the whole cache by myDiskBasedCache.clear() or specific entries by myDiskBasedCache.remove(entryUrl)
Option 2) Custom CacheParser (in the Request)
#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);
}
Option 3) send requests that does not cache
myRequest.setShouldCache(false);
Option 4) use custom Cache implementation
UPDATE:
Example with your code:
//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);
}
};
UPDATE 2
Http protocol caching supports many ways to define how the client can cache responses and when to update them. Volley simplifies those rules to:
entry.ttl (time to live in ms) if greater than the current time then cache can be used otherwise fresh request needs to be made
and
entry.softTtl (soft time to live in ms :) if greater than the current time
cache is absolutely valid and no request to the server needs to be made, otherwise new request is still made (even if the ttl is good) and if there is a change new response will be delivered.
note that if ttl is valid and softTtl is not you can receive 2 onResponse calls
Refering to Setting Up a RequestQueue, I have built an example of a singleton class with caching, in which:
private RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), 10 * 1024 * 1024);
}
return mRequestQueue;
}
In MainActivity.java:
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) {
}
});
My case:
Server data value is 1234:
Wifi connected, run Android app, get value: 1234
Wifi disconnected, run app, get value: 1234
Server data value is updated to 12345678:
Wifi connected, run app, get value: 12345678
Wifi disconnected, run app, get value: 1234
Why Volley doesn't clear then update the cache when getting new data (data different from cached data) from server? How to force that?
I have found a fact (I don't know if it is an answer or not) that mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), 10 * 1024 * 1024); does not cache.
The JsonObjectRequest in my question in fact gets cache which is the result of another request which has the same Url. I will tell in details (sorry for my bad English, perhaps not clear):
In my Android app, firstly I create a JsonObjectRequest as the following:
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; // in 3 minutes cache will be hit, but also refreshed on background
final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
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);
This request runs and caches well, refreshs new data (after 2-3 minutes I guest)
Then, I comment this request (named request A) and create another request (the one in my question, named request B), re-run (Shift-F10) my Android app, and get the issue as in my question. I think B gets the cached data that created before by A.
If wifi disconnected:
At first, only onResponse in B called, but 2-3 minutes later both onResponse and onErrorResponse called (onResponse before onErrorResponse). After the first onErrorResponse called, when app runs again, onErrorResponse called right after onResponse (not after 2-3 minutes anymore). The textView displays cached data (created by A before).
If wifi connected:
only onResponse in B called, however, at first textView displays cached data (created by A before), very soon later, it displayed data from server. I think onResponse called twice.
Then, if I uninstall the Android app from the phone, run app (Shift-F10) again, B does not get cached data anymore.
Volley works well when there is network but it goes weird when network drops.
When network is doping ie network strength is going down and i make a post request then nothing happens but once the network regain to full strength it makes the call to the previous post request not the new one?
when i clear the cache it works well...
how to solve this issue, why i am getting previous post response?
// Implements required listeners
public class VolleyServices<T> implements Response.Listener<T>, ErrorListener{
private int id; // request id
private RequestQueue request; // volley request queue
private VolleyResponce<T> listener; // callback listener
private Class<T> clazz; // parsing class
public interface VolleyResponce<T> {
public void OnSuccess(T response,int id);
public void OnError(ServerError error,int id);
}
// Constructor
public VolleyServices(VolleyResponce<T> listener,Context context) {
this.listener = listener;
request = VolleyRequest.getInstance(context).getRequestQueue();
}
// call to post the request with parse class, post parameters in map and request id
public void post(String methodName, HashMap<String, String> map,Class<T> clazz,int id) {
String url = baseUrl + methodName;
this.clazz = clazz;
this.id = id;
GsonRequest<T> myReq = new GsonRequest<T>(Request.Method.POST,url,clazz,map,this,this);
myReq.setTag(id);
request.add(myReq);
}
#Override
public void onResponse(T response) {
if(response != null && clazz == response.getClass()){
listener.OnSuccess(response,this.id);
}
}
#Override
public void onErrorResponse(VolleyError volleyError) {
ServerError error = null;
if(volleyError instanceof NetworkError) {
error = new ServerError("No internet Access, Check your internet connection.","400");
}
if(volleyError instanceof AuthFailureError) {
error = new ServerError("Authentication Failure","400");
}
if(volleyError instanceof ParseError) {
error = new ServerError("Parsing error","400");
}
if(volleyError instanceof NoConnectionError) {
error = new ServerError("No internet Access, Check your internet connection.","400");
}
if(volleyError instanceof TimeoutError) {
error = new ServerError("Request timed out, Please try again later.","400");
}
if(volleyError.networkResponse != null && volleyError.networkResponse.statusCode == 500) {
error = new ServerError("Internal server error","400");
}
else {
try {
if(volleyError.networkResponse != null) {
String responseBody = new String(volleyError.networkResponse.data, "utf-8" );
try{
Gson gson = new Gson();
error = gson.fromJson(responseBody, ServerError.class);
if(error.status == null) {
error.status = "";
}
}catch(Exception e){
e.printStackTrace();
}
} else {
error = new ServerError("Unknown Error","400");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
listener.OnError(error,this.id);
}
Some log message i captured which explains everything in detail
log link