Volley Increasing ThreadPool Size Android - android

I have this code below which makes 300 http requests and each request returns 10000 rows from database. Total size of 10000 is approximately 0.4mb. So 300*0.4 = 120mb.
Questions:
How increasing the ThreadPool size for handing requests in Volley, can affect the perfomance in app? I change it to 12, but the execution time and size of data was the same as with 4. Is there any difference at all?
When in creasing the number of Volley threads, does the resulted data increase as well? If had 1 thread the maximum returned data each time would be 0.4mb. But if we had 4, the maximum would be 1.6mb.
Emulator: 4 Cores MultiThread
ExecutorService service = Executors.newFixedThreadPool(4);
RequestQueue queue;
AtomicInteger counter = new AtomicInteger(0);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
File cacheDir = new File(this.getCacheDir(), "Volley");
queue = new RequestQueue(new DiskBasedCache(cacheDir), new BasicNetwork(new HurlStack()), 4);
queue.start();
start();
}
public void start(){
String url ="...";
for(int i =0 ; i<300; i++) {
counter.incrementAndGet();
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
method(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("VolleyError", error.toString());
}
});
stringRequest.setTag("a");
queue.add(stringRequest);
}
}
public synchronized void decreased(){
if(counter.decrementAndGet()==0)
start();
}
public void method( String response){
Runnable task = new Runnable() {
#Override
public void run() {
List<Customer> customers= new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
TypeFactory typeFactory = objectMapper.getTypeFactory();
try {
customers= objectMapper.readValue(response, new TypeReference<List<Customer>>() {});
//Simulate database insertion delay
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
decreased();
} catch (IOException e1) {
e1.printStackTrace();
}
}
};
logHeap("");
service.execute(task);
}

Regarding Question 1:
Thread pool with size 4 will be better when compared to 12.
Thread pool size should be in conjunction with number of processors available.
Since the number of processors are limited, app should not spawn unnecessary threads as this may lead to performance problem. As android OS has to manage resource between more threads which will lead to increased wait and actual time for each thread.
Ideally assuming your threads do not have locking such that they do not block each other (independent of each other) and you can assume that the work load (processing) is same, then it turns out that, have a pool size of Runtime.getRuntime().availableProcessors() or availableProcessors() + 1 gives the best results.
Please refer link Setting Ideal size of Thread Pool for more info.
Regarding question 2: If I have understood your question correctly, there should be no change on returned data as thread pool size has no effect on network payload, only wait time and actual time will be changed, when thread pool size value is changed.

Related

Create a queue to send data to PHP server from Android

There I am getting data from SQLite and send it to the server using Volley.
for now, I am sending all the data at a time.
I just want to know how can I create a queue that first data of one vehicle, gets its response and then send another one.
cursor=helperClass.readAllData();
if (cursor!=null)
{
while (cursor.moveToNext())
{
modelClass=new ModelClass(cursor.getInt(0),cursor.getString(1),
cursor.getString(2),cursor.getString(3),
cursor.getString(4),cursor.getString(5));
modelClasses.add(modelClass);
}
sizeOfArray=modelClasses.size();
for (int i=0; i<sizeOfArray;i++)
{
name = modelClasses.get(i).getName();
model=modelClasses.get(i).getModelName();
number=modelClasses.get(i).getEngineNumber();
image=modelClasses.get(i).getImageBase64();
hdimage=modelClasses.get(i).getHdimageBase64();
uploadData(name, model, number, image, hdimage);
Toast.makeText(UploadDataServiceClass.this, String.valueOf(sizeOfArray), Toast.LENGTH_SHORT).show();
Toast.makeText(UploadDataServiceClass.this, String.valueOf(i), Toast.LENGTH_SHORT).show();
}
}
uploadData(name,model,number,image,hdimage)
RequestQueue requestQueue=Volley.newRequestQueue(UploadDataServiceClass.this);
StringRequest stringRequest=new StringRequest(Request.Method.POST, showURL, new Response.Listener<String>()
{
#Override
public void onResponse(String response)
{
try
{
Log.d(TAG, "onResponse: " + response);
JSONObject jsonObject = new JSONObject(response);
}
catch (JSONException e)
{
e.printStackTrace();
}
}
}, new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{ }
}
)
{
#Override
protected Map<String, String> getParams()
{
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("name", name);
parameters.put("model", model);
parameters.put("number", number);
parameters.put("image", image);
parameters.put("hdimage", hdimage);
parameters.put("crud_type", "insert");
return parameters;
}
};
requestQueue.add(stringRequest);
You need a Executor Service with singleThreadExecutor to execute your threads one by one
Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time. Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.
but what is Executor Service ?
with a Executor Service you can set the maximum running tasks (1 in your case)
here is a simple tutorials about ThreadPool , Executors and Future

Retreiving data from MySQL database using Android Volley library is too slow

I tried to retrieve a list of form data stored in database in my Android application. Each row of database contains some personal information of a person in string format and also an image of that person. I have stored the images in database in MEDIUMBLOB format.
Whenever I try to retrieve data from my server using JSONObjectrequest of Volley Library in my Android app, the response is usually very slow. Sometimes it takes more than 1 minute to view only 10 to 12 rows retrieved from the database.
This is my logcat:
D/Volley: [337] BasicNetwork.logSlowRequests: HTTP response for request=<[ ] http://helpclick.ahsanaasim.me/v1/tasksall/johny 0xa3e020c1 NORMAL 1> [lifetime=14740],
I tried to search for a perfect solution but I couldn't find anything satisfactory. Here is my Java code:
mRequestStartTime = System.currentTimeMillis();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
showUrl2, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
long totalRequestTime = System.currentTimeMillis() - mRequestStartTime;
System.out.println(totalRequestTime);
System.out.println(response.toString());
try { c1++;
System.out.println(c1);
JSONArray incidents = response.getJSONArray("incidents");
for (int i = 0; i < incidents.length(); i++) {
e=0;
JSONObject incident = incidents.getJSONObject(i);
c1++;
id= incident.getString("id");
age = incident.getString("age");
gender = incident.getString("gender");
location = incident.getString("location");
//det= incident.getString("det");
String image=new String();
image = incident.getString("bigimage");
if(image.length()!=0) {
myBitmap = ConvertToImage(image);
Bitmap bitmap= Bitmap.createScaledBitmap(myBitmap,500,500,true);
imgs.add(bitmap);
ages.add(age);
genders.add(gender);
locations.add(location);
ids.add(id);
}
}
if(c1>0) {
System.out.println(ages.size());
Intent intent1 = new Intent(search_buttons_page.this, All_Incidents.class);
startActivity(intent1);
}
}
catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.append(error.getMessage());
}
});
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(
20000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
requestQueue.add(jsonObjectRequest);
It would be really helpful if someone can tell me the reason of this slow performance and how to solve it by making minimum modifications in my source code.
Don't keep the images in the db. Keep them in files, and keep the URL of the files in the db. Download the images separately as needed via URL. Then you aren't killing your database access times with what should be file IO.

Android Volley Error Null using Stored Procedures in EF

Im consuming a RESTful Api builded with ASP EF. I have a procedure in my DB, this is it:
ALTER PROCEDURE [Ventas].[CtasxCobxVendedor]
#AGE CHAR(1),
#VENDEDOR VARCHAR(10)
AS
BEGIN
SET NOCOUNT ON
SELECT
V.CLIENTE Codigo,
C.RazonSocialAnalitico Cliente,
C.DireccionAnalitico Direccion,
C.TelefonoAnalitico Telefono,
V.Gestion,
V.IdDos,
V.DCTO,
V.Factura,
V.Fecha,
V.Vencimiento,
SUM(B.DBB) Monto,
SUM(B.HBB) Pagos,
SUM(B.DBB-B.HBB) Saldo
FROM VENTAS.VMAESTRO V
JOIN VENTAS.CTASXCOBRAR B ON
(V.GESTION=B.GESTIONF
AND V.AGE =B.AGE
AND V.TIPO = B.TIPOF
AND V.IDDOS = B.IDDOSF
AND V.DCTO = B.DCTOF)
JOIN VENTAS.vwCLIENTES C ON
(V.CLIENTE = C.IdAnalitico)
WHERE
-- V.AGE =#AGE
V.STA = 'A'
AND V.VENDEDOR = #VENDEDOR
GROUP BY V.CLIENTE,C.RazonSocialAnalitico,C.DireccionAnalitico,C.TELEFONOAnalitico,V.Gestion,V.IdDos,V.DCTO,V.Factura,V.FECHA,V.VENCIMIENTO
HAVING SUM(B.DBB-B.HBB) > 0.001
ORDER BY C.RazonSocialAnalitico, V.FECHA, V.DCTO;
RETURN 0;
END
I created the import function, and the Complex Type on VS. So this is what I got:
public virtual ObjectResult<CtasxCobxVendedor_Result> CtasxCobrarV(string aGE, string vENDEDOR)
{
var aGEParameter = aGE != null ?
new ObjectParameter("AGE", aGE) :
new ObjectParameter("AGE", typeof(string));
var vENDEDORParameter = vENDEDOR != null ?
new ObjectParameter("VENDEDOR", vENDEDOR) :
new ObjectParameter("VENDEDOR", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<CtasxCobxVendedor_Result>("CtasxCobrarV", aGEParameter, vENDEDORParameter);
}
Then I tried to call this SP in one of my controllers, in this case is my Personal controller, like this:
public IQueryable<CtasxCobxVendedor_Result1> GetCuenta(string id)
{
using (NemesisEntities ctx = new NemesisEntities()) {
return db.CtasxCobxVendedor("A", id).AsQueryable();
}
}
When I call this method on the browser (like this "localhost:45896/api/personals/3329672" where "3329672" is the Personal Id) works just fine, cause it gives me this result:
[{"Codigo":"1018389023","Cliente":"BAREMSA","Direccion":"Av. Cicunvalación - ITOS S/N","Telefono":"","Gestion":"15","IdDos":503,"DCTO":15001980,"Factura":1097,"Fecha":"2015-10-21T00:00:00","Vencimiento":"2015-11-20T00:00:00","Monto":1380.0000,"Pagos":0.0000,"Saldo":1380.0000},{"Codigo":"1018389023","Cliente":"BAREMSA","Direccion":"Av. Cicunvalación - ITOS S/N","Telefono":"","Gestion":"15","IdDos":509,"DCTO":15002329,"Factura":128,"Fecha":"2015-12-09T00:00:00","Vencimiento":"2016-01-08T00:00:00","Monto":1980.0000,"Pagos":0.0000,"Saldo":1980.0000},{"Codigo":"3095060012","Cliente":"BERTHA CONDORI ORURO","Direccion":"","Telefono":" 25288136","Gestion":"15","IdDos":509,"DCTO":15002349,"Factura":148,"Fecha":"2015-12-11T00:00:00","Vencimiento":"2016-01-10T00:00:00","Monto":1450.0000,"Pagos":0.0000,"Saldo":1450.0000},{"Codigo":"1015777022","Cliente":"CADEXNOR","Direccion":"","Telefono":"","Gestion":"16","IdDos":509,"DCTO":16000384,"Factura":661,"Fecha":"2016-03-09T00:00:00","Vencimiento":"2016-04-08T00:00:00","Monto":1440.0000,"Pagos":0.0000,"Saldo":1440.0000},{"Codigo":"1006965023","Cliente":"COMIBOL","Direccion":"Plaza 6 de Agosto","Telefono":" 68224768","Gestion":"14","IdDos":10,"DCTO":14000142,"Factura":314,"Fecha":"2012-08-03T00:00:00","Vencimiento":"2012-08-08T00:00:00","Monto":2770.0000,"Pagos":0.0000,"Saldo":2770.0000},{"Codigo":"1006965023","Cliente":"COMIBOL","Direccion":"Plaza 6 de Agosto","Telefono":" 68224768","Gestion":"14","IdDos":10,"DCTO":14000143,"Factura":776,"Fecha":"2013-10-03T00:00:00","Vencimiento":"2013-11-02T00:00:00","Monto":2900.0000,"Pagos":0.0000,"Saldo":2900.0000}]
Then when I try to connect it to my Android app using Volley framework:
JsonArrayRequest re= new JsonArrayRequest(Request.Method.GET, newURL, (String)null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Toast.makeText(Cobrar.this,response.toString(),Toast.LENGTH_LONG).show();
procesarRespuesta(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(Cobrar.this,"NOTHING",Toast.LENGTH_LONG).show();
Log.d(TAG, "Error Volley: " + error.getMessage());
}
});
Where "newURL" is like the one above. Just Give me "Error Volley:null" without any other explanation.
I really dont know what to fix, cause when I use simple GET calls for example calling this: "http://localhost:45896/api/clientes", it works fine, the problem is when I want to use the SP.
Any idea of what am I doind wrong? Since I dont get any information of where my problem actually is, Idk where to start
Please check this question posted here.
I have faced same issue.
Why this happens?
In volley, When timeout/socket timeout occurs it throws error. but
error object is null. You can override two methods in your Request
class to check if its timeout.
Solution :
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, "url", "request", new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected void deliverResponse(JSONObject response) {
super.deliverResponse(response);
}
#Override
public void deliverError(VolleyError error) {
super.deliverError(error);
}
};
You can get error on deliverError method in above code.
TimeOut occurs when server takes more time to respond to app then defined in RetryPolicy.
request.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS * 48,
0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
default timeout is 2500 seconds for Volley.
You can avoid this issue using following improvements :
You need to improve your server performance
You can set retryCount to 1 if it suits your app requirements.
Thanks.

JsonObjectRequest in Android sending multiple requests

I am building an android application in which some data is sent to server from the android device, every 1 second for 30 seconds. (total 30 requests to server).
I am using a for loop for this :
for(i=0;i<30;i++){
//Some data computation
JsonObjectRequest req = new JsonObjectRequest(url, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
VolleyLog.v("Response:%n %s", response.toString(4));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
});
}
I am getting more than 30 enteries at my server end.
Is the JsonObjectRequest is sending multiple requests in every iteration?
Volley makes multiple requests to the server by default (Default Retry Policy).
These Settings can be found in DefaultRetryPolicy.java.
So according to this default policy, Volley tries to wait for the response for 2500 milliseconds, however if the response is not received in this time span then it retries for the number set by the DEFAULT_MAX_RETRIES, i.e., 1. And the DEFAULT_BACKOFF_MULT variable is used to determine exponential time set to socket for every retry attempt.
/** The default socket timeout in milliseconds */
public static final int DEFAULT_TIMEOUT_MS = 2500;
/** The default number of retries */
public static final int DEFAULT_MAX_RETRIES = 0;
/** The default backoff multiplier */
public static final float DEFAULT_BACKOFF_MULT = 1f;
Now, to stop the multiple request you can configure retry policy for your request object by using the setRetryPolicy() method of the request object.
//req = Request
req.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
Reference : Here

How to wait for RequestQueue job to finish?

I'm trying to create a login page for my app. I check the credentials by doing a get request to a web server which is tied in to my user database.
public boolean checkCredentials(String email, String password) throws JSONException {
// Make a get request to the server
String url = MyUtils.createLoginUrl(email, password);
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, requestParam, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
successLogin = response.length() > 0;
jsonResponse = response.length() > 0 ? response : null;
//requestPending -= 1;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
MyUtils.showToast(getBaseContext(), error.getMessage().toString());
//requestPending -= 1;
}
});
SingletonRequestQueue.getInstance(this).addToRequestQueue(jsObjRequest);
//requestPending += 1;
// I WANT THE JOB TO FINISH BEFORE RETURNING FROM THIS FUNCTION
return successLogin;
}
Is there a non-blocking way to do this using the Volley library? Google wasn't giving me much info.
You can't with Volley and you shoudn't with other tools. Long running operations like going to database or to network block the UI thread which is a bad practice since the user can't interact to the UI.
Talking about volley, it does all this job asynchronous in three thread levels:
UI
Cache
Network
See here the schema.
All three levels allows the system to cache the responses and use a pool thread to dispatch all the requests at the same time if enough space and memory.
Some time ago people recommended you to do:
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
This avoided the NetworkOnMainThreadException, but as I told you before it is a really bad practice because you will be skipping a bunch of frames by waiting.
I know listeners are a pain, but all we have to live with them in Android Dev.

Categories

Resources