Android volley get request does not work on first time - android

I would like to send a new JsonObjectRequest request (GET)
Here is my code below:
final VolleyApplication volleyApplication = VolleyApplication.getInstance();
volleyApplication.init(getApplicationContext());
JsonArrayRequest req = new JsonArrayRequest("http://localhost:8080/webapi/", new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
VolleyLog.v("Response:%n %s", response.toString(4));
System.out.print(response.toString());
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
Type listType = new TypeToken<List<MyEntity>>() {
}.getType();
myList = gson.fromJson(response.toString(), listType);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
System.out.print(error.getMessage());
}
}
);
RequestQueue requestQueue = volleyApplication.getRequestQueue();
requestQueue.add(req);
this works on onCreate and list some object but it does not. As i see in debug mode,process works two times for this method. In first time when it is at RequestQueue requestQueue = volleyApplication.getRequestQueue(); requestQueue.add(req);.... line
it jumps out to end of the method. But it works and gets data for second time. This messed up my code.
And also my VolleyApplication class here below
public final class VolleyApplication {
private static VolleyApplication instance = null;
public static final VolleyApplication getInstance() {
if (instance == null) {
instance = new VolleyApplication();
}
return instance;
}
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private boolean initialized = false;
private VolleyApplication() {
}
public void init(final Context context) {
if (initialized) {
return;
}
requestQueue = Volley.newRequestQueue(context);
int memory = ((ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();
int cacheSize = 1024 * 1024 * memory / 8;
// imageLoader = new ImageLoader(requestQueue, new BitmapLruCache(cacheSize));
}
public RequestQueue getRequestQueue() {
if (requestQueue == null) {
throw new RuntimeException("Init first");
}
return requestQueue;
}
public ImageLoader getImageLoader() {
if (imageLoader == null) {
throw new RuntimeException("Init first");
}
return imageLoader;
}
}

#seradd
You are interpreting it wrong.
It is actually executing only one time.
What you are seeing in debug mode is that,
First time it is creating requestObject and adding it to RequestQueue.
RequestQueue then execute it and once it will get response from URL it will execute its callback functions onResponse() and onErrorResponse() from Response.Listener and Response.ErrorListener interface respectively.
So what I suggest you , whatever task you are doing after adding task
to RequestQueue call add that code to onResponse() method

Related

Volley using StringRequest not calling getParams for sending POST Request Parameters after 1st time

I am facing a problem where my POST request parameters are not going to server after 1st time. I know Volley is using cache mechanism for responses, but in my case my request parameter values can be changed at runtime as i am using pagination in Recyclerview.
So my questions is how can i send Post request parameter every time and wont loose cache mechanism of volley.
I have tried using below ones and get my things done (calling getParams() every-time).. but it loses caches response and i don't want that.
requestQueue.getCache().clear();
stringRequest.setShouldCache(false);
Also have Searched Google and below links but cant find any proper solution. below are the SO links
Volley not calling getParams() for second time
Volley not calling getParams()
Android volley does not calling getParams in POST request
Volley not calling getParams() for standard POST request
Below is my code:
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("RES", response);
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setDateFormat("M/d/yy hh:mm a"); //Format of our JSON dates
Gson gson = gsonBuilder.create();
NewsFeedPOJO resultObj = (NewsFeedPOJO) gson.fromJson(response, (Class) NewsFeedPOJO.class);
inCurrPage = Integer.parseInt(resultObj.getPagination().getCurrent_page());
inTotalPage = Integer.parseInt(resultObj.getPagination().getTotal_pages());
inCurrPage++;
arrayList.addAll(resultObj.getNewsFeedList());
if (isFtym) {
isFtym = false;
layoutManager = new LinearLayoutManager(MainActivity.this);
rcNewsFeed.setLayoutManager(layoutManager);
adapter = new NewsFeedAdapter(MainActivity.this, arrayList);
rcNewsFeed.setAdapter(adapter);
} else {
adapter.notifyItemInserted(arrayList.size());
adapter.notifyDataSetChanged();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put("user_id", "188");
if (inCurrPage == 0)
map.put("page", "1");
else {
map.put("page", "" + inCurrPage);
}
Log.e("RES", inCurrPage + " PARA");
return map;
}
};
//RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
//requestQueue.add(stringRequest);
//requestQueue.getCache().clear();
//AppController.getInstance().addToRequestQueue(stringRequest);
// stringRequest.setShouldCache(false);
VolleySingleton.getInstance(this).addToRequestQueue(stringRequest);
using below Volley Dependency.
compile 'com.android.volley:volley:1.1.0'
If need more information please do let me know. Thanks in advance. Your efforts will be appreciated.
Did you check your Volley Singleton?
import android.content.Context;
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;
public class VolleySingleton {
private static AppSingleton mAppSingletonInstance;
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static Context mContext;
private AppSingleton(Context context) {
mContext = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static synchronized AppSingleton getInstance(Context context) {
if (mAppSingletonInstance == null) {
mAppSingletonInstance = new AppSingleton(context);
}
return mAppSingletonInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
// getApplicationContext() is key, it keeps you from leaking the
// Activity or BroadcastReceiver if someone passes one in.
mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req,String tag) {
req.setTag(tag);
getRequestQueue().add(req);
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Or maybe there is another issue in your code...

Android prepare waiting mechanism or correct synchronize to service

in my Android project i try to prepare waiting mechanism or correct synchronize to intent service to handle multi concurrency requests user. for example after click on button, my application try to get data on server with Service,
after click on the button, user maybe try to click on that again, for manage this operation i coding below sample to handle multi concurrency requests user, such as waiting to finish request with create an requests path.
but in this code i cont know how to create requests stack, that means they must run by order's requests.
now is my code correct?
Volley Simple Singleton Class:
public class CustomVolleyRequestQueue {
private static CustomVolleyRequestQueue mInstance;
private static Context context;
private RequestQueue mRequestQueue;
private CustomVolleyRequestQueue(Context context) {
this.context = context;
mRequestQueue = getRequestQueue();
}
public static synchronized CustomVolleyRequestQueue getInstance(Context context) {
if (mInstance == null) {
mInstance = new CustomVolleyRequestQueue(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
Cache cache = new DiskBasedCache(context.getCacheDir(), 10 * 1024 * 1024);
Network network = new BasicNetwork(new HurlStack());
mRequestQueue = new RequestQueue(cache, network);
// start the volley request queue
mRequestQueue.start();
}
return mRequestQueue;
}
}
Intent Service:
public class WebService extends IntentService {
public static final String REQUEST_TAG = "SimpleWebServiceBlockingRequest";
private RequestQueue mQueue;
private Object isReceiveMessagesLock;
public WebService() {
super("WebService");
}
public WebService(String name) {
super("WebService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
Bundle data = intent.getExtras();
if (data != null) {
String url = data.getString("url");
synchronized (isReceiveMessagesLock) {
if (isReceiveMessagesLock != null) {
return;
} else {
try {
isReceiveMessagesLock.wait();
startParsingTask(url); //receiving start
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public void startParsingTask(final String url) {
Thread prepaire_request_thread = new Thread() {
public void run() {
ThreadB request_from_servcer_thread = new ThreadB(getApplicationContext(), url);
JSONObject json_object = null;
try {
json_object = request_from_servcer_thread.execute().get(10, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
if (json_object != null) {
Log.e("OUTPUT: ", json_object.toString());
}
}
};
prepaire_request_thread.start();
}
private class ThreadB extends AsyncTask<Void, Void, JSONObject> {
private Context context;
private String fetch_url = "";
public ThreadB(Context ctx, String url) {
context = ctx;
this.fetch_url = url;
}
#Override
protected JSONObject doInBackground(Void... params) {
final RequestFuture<JSONObject> futureRequest = RequestFuture.newFuture();
mQueue = CustomVolleyRequestQueue.getInstance(context.getApplicationContext())
.getRequestQueue();
final JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method
.GET, fetch_url,
new JSONObject(), futureRequest, futureRequest);
jsonRequest.setTag(REQUEST_TAG);
mQueue.add(jsonRequest);
try {
return futureRequest.get(10, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
return null;
}
}
}
POST UPDATED:
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
Bundle data = intent.getExtras();
if (data != null) {
String url = data.getString("url");
startParsingTask(url); //receiving start
}
}
}
IntentService already handles one call per time, you don't need syncronize or anything else.
Volley supports also multiple calls, so you won't have any problem of concurrency at all.
After that, if you are calling APIs, you may want to try retrofit ( http://square.github.io/retrofit/ ) or at least use GSON to deserialize JSON data.

Is volley cache present even after the app is destroyed and the user reenters?

This is my CustomVolleyRequestQueue
private CustomVolleyRequestQueue(Context context) {
mCtx = context;
mRequestQueue = getRequestQueue();
mImageLoader = new ImageLoader(mRequestQueue,
new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap>
cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static synchronized CustomVolleyRequestQueue getInstance(Context context) {
if (mInstance == null) {
mInstance = new CustomVolleyRequestQueue(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
Cache cache = new DiskBasedCache(mCtx.getCacheDir(), 10 * 1024 * 1024);
Network network = new BasicNetwork(new HurlStack());
mRequestQueue = new RequestQueue(cache, network);
// Don't forget to start the volley request queue
mRequestQueue.start();
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
return mImageLoader;
}
}
I use it to display NetworkImages in a RecyclerAdapter. This is how I initialize the imageLoader ImageLoader mImageLoader = CustomVolleyRequestQueue.getInstance(this.getActivity())
.getImageLoader();
and this is how I use it :
holder.imageView.setImageUrl(listItems.getImagePath(), mImageLoader);
getImagePath()- simply returns an url
Everything is working fine. What I want to do now is to retrieve that cache and display the images from cache if it is present(no internet) after the app was killed. How can I achieve this ?
Edit : I added this to be done when I click a button.
Cache cache = CustomVolleyRequestQueue.getInstance(getActivity()).getRequestQueue().getCache();
Cache.Entry entry = cache.get("urlThatIKnowWasLoaded");
if (entry != null) {
try {
Log.d("askj","Cache is present");
String data = new String(entry.data, "UTF-8");
// handle data, like converting it to xml, json, bitmap etc.,
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else
Log.d("askj","Cache is not present");
{
// Cached response doesn't exists. Make network call here
}
I click this button after the data was loaded so I know that it is present in the cache(I can go back form that Activity and reenter in it and the images are there in no time), but I get that "Cache is not present". Clearly this approach has something wrong. How can I solve it ?

how to create common class for volley library in android

I want to create one base class for volley library and want to access the response and Error on the Activity where i called the volley request.because of this my code will optimize.
Personally am using following classes for handling volley.you can revert it as per the requirement.
Volley Request Queue Helper :
public class VolleyHelper {
private static final String TAG = VolleyHelper.class
.getSimpleName();
private RequestQueue mRequestQueue;
private static VolleyHelper mInstance;
public VolleyHelper (Context context) {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(context);
}
}
public static synchronized VolleyHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new VolleyHelper(context);
}
return mInstance;
}
public RequestQueue getRequestQueue() {
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Ideally you should have one centralized place for your Queue, and the best place to initialize queue is in your Application class. Above snippet interpret how this can be done
Volley Error Helper
public class VolleyErrorHelper {
/**
* Returns appropriate message which is to be displayed to the user
* against the specified error object.
*
* #param error
* #param context
* #return
*/
public static String getMessage(Object error, Context context) {
if (error instanceof TimeoutError) {
return context.getResources().getString(R.string.generic_server_down);
} else if (isServerProblem(error)) {
return handleServerError(error, context);
} else if (isNetworkProblem(error)) {
return context.getResources().getString(R.string.no_internet);
}
return context.getResources().getString(R.string.generic_error);
}
/**
* Determines whether the error is related to network
*
* #param error
* #return
*/
private static boolean isNetworkProblem(Object error) {
return (error instanceof NetworkError) || (error instanceof NoConnectionError);
}
/**
* Determines whether the error is related to server
*
* #param error
* #return
*/
private static boolean isServerProblem(Object error) {
return (error instanceof ServerError) || (error instanceof AuthFailureError);
}
/**
* Handles the server error, tries to determine whether to show a stock message or to
* show a message retrieved from the server.
*
* #param err
* #param context
* #return
*/
private static String handleServerError(Object err, Context context) {
VolleyError error = (VolleyError) err;
NetworkResponse response = error.networkResponse;
if (response != null) {
switch (response.statusCode) {
case 409:
return context.getResources().getString(R.string.user_exists);
case 404:
break;
case 422:
break;
case 401:
try {
// server might return error like this { "error": "Some error occured" }
// Use "Gson" to parse the result
HashMap<String, String> result = new Gson().fromJson(new String(response.data),
new TypeToken<Map<String, String>>() {
}.getType());
if (result != null && result.containsKey("error")) {
return result.get("error");
}
} catch (Exception e) {
e.printStackTrace();
}
// invalid request
return error.getMessage() != null ? error.getMessage() : context.getResources().getString(R.string.generic_error);
default:
return context.getResources().getString(R.string.generic_server_down);
}
}
return context.getResources().getString(R.string.generic_error);
}
}
Volley Response Helper
public class VolleyResponseHelper {
/**
* Returns appropriate message which is to be displayed to the user
* against the specified response .
*
* #param code
* #param context
* #return
*/
/* 0 - Request from registration */
/* 1 - Request from login */
/* 2 - Request from New post */
public static String getMessage(String code, int from, Context context) {
int mCode = Integer.parseInt(code);
String message = null;
switch (mCode) {
case 409:
if (from == 1 || from == 0) {
message = context.getResources().getString(R.string.user_exists);
}
return message;
case 200:
if (from == 1 || from == 0) {
message = context.getResources().getString(R.string.success);
} else if (from == 2) {
message = context.getResources().getString(R.string.np_done);
}
return message;
case 401:
if (from == 1) {
message = context.getResources().getString(R.string.user_not_exists);
}
return message;
default:
return context.getResources().getString(R.string.generic_error);
}
}
}
Inside volley onErrorResponse
#Override
public void onErrorResponse(VolleyError error) {
String errorString = VolleyErrorHelper.getMessage(error, context);
if (errorString != null) {
showAlert(errorString);
}
}
For more clear about usage i have posted my code revert it like your requirement
private void getDetails(Map<String, String> params) {
SalonJsonObjReq arrayReq = new SalonJsonObjReq(Request.Method.POST, Constants.SALON_DETAILS, new JSONObject(params), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
populate(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideProgressDialog();
String errorString = VolleyErrorHelper.getMessage(error, DetailsScreen.this);
if (errorString != null) {
Util.showAlert(DetailsScreen.this, getResources().getString(R.string.error), errorString);
}
}
}, null);
showProgressDialog(getResources().getString(R.string.loading));
VolleyHelper.getInstance(getApplicationContext()).addToRequestQueue(arrayReq);
}
ResponseHelper also you can use on this way.apply your logic :)
Check this for more.
I use VolleyService in Util app folder as following :
public class VolleyService {
private static VolleyService instance;
private RequestQueue requestQueue;
private ImageLoader imageLoader;
private VolleyService(Context context) {
requestQueue = Volley.newRequestQueue(context);
imageLoader = new ImageLoader(requestQueue, new ImageLoader.ImageCache() {
private final LruCache<String, Bitmap> cache = new LruCache<String, Bitmap>(20);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url,bitmap);
}
});
}
public static VolleyService getInstance(Context context) {
if (instance == null) {
instance = new VolleyService(context);
}
return instance;
}
public RequestQueue getRequestQueue() {
return requestQueue;
}
public ImageLoader getImageLoader() {
return imageLoader;
}
}
And when I need an instance i just use :
VolleyService.getInstance(context)
Or creating the request :
RequestQueue queue = VolleyService.getInstance(this.getContext()).getRequestQueue();
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// we got the response, now our job is to handle it
try {
updateArticleData(response, syncResult,categoryID);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//something happened, treat the error.
Log.e("Error", error.toString());
}
});
queue.add(request);

Volley does not stop adding date to listview from json

I want app to show dates in listview. My app has TabLayout which imitates this and Listviews which imitate this.So, tabs have listview. After showing all json dates in listview, they load json dates again. It happens when I swipe each tabs like tab1→tab2→tab3→tab1→tab3.... This is may code. If anyone knows what is wrong, please teach me.
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private ImageLoader mImageLoader;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public ImageLoader getImageLoader() {
getRequestQueue();
if (mImageLoader == null) {
mImageLoader = new ImageLoader(this.mRequestQueue,
new LruBitmapCache());
}
return this.mImageLoader;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
// set the default tag if tag is empty
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
Tab 1 (Tab2 and Tab3 are almost same)
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
adapter = new CSadapter(getActivity(),movieList);
setListAdapter(adapter);
getListView().setScrollingCacheEnabled(false);
pDialog = new ProgressDialog(getActivity());
// Showing progress dialog before making http request
pDialog.setMessage("Loading...");
pDialog.show();
// Creating volley request obj
JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Song movie = new Song();
movie.setTitle(obj.getString("title"));
movie.setThumbnailUrl(obj.getString("jacket"));
movie.setNumber(obj.getString("number"));
movie.setYear(obj.getString("release"));
// adding movie to movies array
movieList.add(movie);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(movieReq);
}
In a pager the default page limit is 1 .If you go beyond that your page activity is created again.This may be the case happening here.You can increase the page limit to avoid re creation

Categories

Resources