Android sleep between AsyncTasks (more than 128) - android

Note: The app I am working on is for PERSONAL use only. I am trying to collect data for my master thesis.
I am trying to start more than 128 AsyncTasks at once, which fails because of the ThreadPoolExecutor. I've seen some answers why it is not working, but no real answer of how to implement it correctly.
As I have a lot of time for uploading my stuff I was considering to just put my MainActivity to sleep before starting the next upload, which does not seem to work as well.
for (IrisResult s : results) {
try {
Thread.sleep(1000);
mAzureTableManager.addIrisResult(s);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The method addirisResult() actually starts the AsyncTask by protected Void doInBackground(Void... params) {
I am looking for the SIMPLEST solution, not for the best approach!

yourAsyncTask.executeOnExecutor(yourThreadPoolExecutor, params);
And increase your pool size:
yourThreadPoolExecutor.setMaximumPoolSize(size);
Sets the maximum allowed number of threads. This overrides any value set in the constructor. If the new value is smaller than the current value, excess existing threads will be terminated when they next become idle.
android.developer.com - ThreadPoolExecutor#setMaximumPoolSize(int)
android.developer.com - AsyncTask#executeOnExecutor(Executor, Params...)
as an example:
yourThreadPoolExecutor = Executors.newCachedThreadPool();
yourThreadPoolExecutor.setMaximumPoolSize(256);
yourAsyncTask.executeOnExecutor(yourThreadPoolExecutor, params);

Related

Alternative for SystemClock.sleep in Android Espresso

I am writing my test cases for my app however have come into some minor problems. Many of my test cases have SystemClock.Sleep calls in them, in order for the view to load all the data and display it on the screen. However the number of sleeps to do this has increasingly grown causing the time of these tests to be even longer.
Here is an example of one of these tests
#Test
public void testSearch() {
ExtensionForExpresso.signUp();
SystemClock.sleep(17000);
onView(withId(R.id.menu_offer_search)).check(matches(isDisplayed())).perform(click());
SystemClock.sleep(5000);
onView(withId(R.id.menu_search)).check(matches(isDisplayed())).perform(typeText("Pizza"));
SystemClock.sleep(17000);
onView(withId(R.id.searchSectionSeeAllButton)).check(matches(isDisplayed())).perform(click());
SystemClock.sleep(15000);
onView(withId(R.id.searchResultsRecyclerView)).check(matches(isDisplayed())).perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
}
Is there an alternative to sleep that will wait for view to appear? Or are there any methods or functions I can add in to reduce the amount of SystemClock.sleep calls?
First, try to disable animation on your device/emulator using adb shell or implement the Espresso Idling Resource in your Android project: http://matgom.com/tutorial/2016/02/21/IdlingResource.html
I would recommend you to implement an IdlingResource and Disable the system animations first. The easiest way to disable system animations is this.
There is no need to use the SystemClock.sleep() method. Instead you could implement a custom sleep method like this:
public void waitFor(int seconds) {
seconds = seconds < 0 ? 0 : seconds;
while (--seconds >= 0) {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Then you could call it in your test like: waitFor(2); // 2 second wait

Ensure UI Thread isn't interrupted

I have a GridView full of somewhat complicated views, that are computed based on results downloaded on the fly from the internet in an AsyncTask. While the view is being downloaded, it shows a default:
imageView.setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
When the AsyncTask finishes it gets a Bitmap that was computed for it. I am using an ExecutorService to enable AsyncTask parallelization:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
loaderPool = Executors.newFixedThreadPool(backendManager.getBackendApplicationContext()
.getResources()
.getInteger(R.integer.loader_thread_count));
}
(I've currently set R.integer.loader_thread_count to 10)
And I start those AsyncTask's as:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
newTask.executeOnExecutor(loaderPool);
} else {
newTask.execute(); // Pre-Honeycomb Post-Donut is parallelized by default.
}
I make sure to set the thread priority in the AsyncTask so that it doesn't try to compete with anything else:
#Override
protected Object doInBackground(Object... params) {
if (isCancelled()) {
return null;
}
// just in case
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
...
But, the ui feels jerky when scrolling the GridView. The issue seems to be that the main thread is getting pre-empted too often:
I would like a large number of threads for when there is high network latency, so that they can all be blocking on network io when necessary. However, I only want those threads to run when the ui has essentially nothing else to do; I'm fine showing transparent views for a while while everything loads, so long as the ui is responsive while it is loading (there are some text views and stuff too so it's not just a blank screen).
How can I instruct android to give greater priority to my ui thread, and/or less priority to my AsyncTasks?
I would like a better answer, but for now this seemed to help a bunch.
While the docs claim for the higher thread priorities that "Applications can not normally change to
this priority", as of a few years ago that was a lie, and seems (?) to apparently still be a lie - https://groups.google.com/forum/#!topic/android-developers/b2SKprSxPvw
As such rather than make the background threads more backgrounded, I made the ui thread more foregrounded in Activity.onCreate(). In case they disallow this sort of thing in the future, I wrap it with a try/catch:
try {
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_DISPLAY);
} catch (Throwable t) {}

Android dynamic UI update from AsynchTask/Handler and Thread priorities

I am using an AsynchTask to host a simulator that runs indefinelly and posts the results after each simulation step.
Limiting the simulation loop in background at a maximum of 25Hz, and only calling a javascript function with the results, it works "fine".
Apart from updating a webgl model in a browser, what looks fast enough, I have two more things to update from the Android UI: the FPS indicator and the panel with TextViews representing some of the values. If we forget about the FPS:
The onProgressUpdate() function is already limited to be called at 25Hz, to refresh the model. Now I use another time variable to limit, inside this method, the call to another method that updates the UI panel textViews. It is limited to 1Hz, less than what I actually wanted but fast enough for the kind of information. The method is as clean as possible, all the views are previously loaded to a variable that I keep to not load them every time.
What is the effect: looks like updating 5 textViews takes like one second where all the UI freezes, the touch moves are very very laggy...
I decreased the priority of the background task with:
#Override
protected Boolean doInBackground(ModelSimulation... params) {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
...
And used Thread.yield() at the end of the doInBackground method. This improves the behavior to what I explained, without these commands, the behavior is even worst.
My questions are:
-Can I reduce even more the priority if instead of using a background task I use a handler and my own Thread?
-Will a service improve the behavior of the UI?
-Why updating 5 textViews takes so long compared with calling a javascript function that finally will have to use the gpu to change the webgl model?
-Is Android not prepared in any sens to do dynamic applications? How applications like the ones to test sensors update so fast the UI? because there are not standar components like the textViews? (like browser going faster than a textView)
Note: even reducing the refreshing limitations, it produce a laggy effect every time the HUD is updated. In fact I talk about 5 textViews but only updating the FPS indicator produces the same pause. Looks like the only fact of having to switch to the UI thread already consumes this time.
Edit 1:
#Override
protected Boolean doInBackground(ModelSimulation... params) {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
if(simulator.getSimulatorStatus().equals(SimulatorStatus.Connected)){
try {
while (true){
//TODO Propagate
long dur = (System.nanoTime()-time_tmp_data);
if(dur<Parameters.Simulator.min_hud_model_refreshing_interval_ns){
try {
long sleep_dur = (Parameters.Simulator.min_hud_model_refreshing_interval_ns-(System.nanoTime()-time_tmp_data))/1000000;
if(sleep_dur>0){
Thread.sleep(sleep_dur);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
time_tmp_data = System.nanoTime();
SpacecraftState sstate = propagate();
int progress = (int)((extrapDate.durationFrom(finalDate)/mission.sim_duration)*100);
if(sstate!=null){
SimResults results = new SimResults(sstate, progress);
simulator.getSimulationResults().updateSimulation(results.spacecraftState, results.sim_progress);
publishProgress();
}
if(isCancelled())
break;
Thread.yield();
}
} catch (OrekitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
simulator.showMessage(simulator.getContext().getString(R.string.sim_orekit_prop_error)+": "+e.getMessage());
}
}
return true;
}
#Override
protected void onProgressUpdate(Void... values) {
//Update model by push
simulator.getSimulationResults().pushSimulationModel();
//Update GUI HUD
if(time_tmp_gui==0 || (System.nanoTime()-time_tmp_gui)>Parameters.Simulator.min_hud_panel_refreshing_interval_ns){
time_tmp_gui = System.nanoTime();
simulator.getSimulationResults().updateHUD();
}
}
If I comment the line simulator.getSimulationResults().updateHUD(); or directly the contents of the method, it works "fine". And this method is only changing some textviews text:
public synchronized void updateHUD(){
//Log.d("Sim",System.currentTimeMillis()+": "+"pre update gui 1");
activity.runOnUiThread( new Runnable() {
#SuppressLint("ResourceAsColor")
public void run() {
if(view != null){
if(panel_time != null)
panel_time.setText(info.time.replace("T", " "));
if(panel_progress != null)
panel_progress.setProgress(info.progress);
if(panel_vel != null){
panel_vel.setText("Vel. "+String.format("%.2f", info.velocity)+" Km/s");
if(info.velocity>config.limit_velocity)
panel_vel.setTextColor(activity.getResources().getColor(R.color.panel_limit));
else
panel_vel.setTextColor(activity.getResources().getColor(R.color.panel_value));
}
if(panel_accel != null){
panel_accel.setText("Accel. "+String.format("%.2f", info.acceleration)+" Km/s2");
if(info.acceleration>config.limit_acceleration)
panel_accel.setTextColor(activity.getResources().getColor(R.color.panel_limit));
else
panel_accel.setTextColor(activity.getResources().getColor(R.color.panel_value));
}
if(panel_radium != null)
panel_radium.setText("Orbit radium: "+String.format("%.1f", info.orbit_radium)+" Km");
if(panel_mass != null)
panel_mass.setText("Mass: "+String.format("%.1f", info.mass)+" Kg");
if(panel_roll != null)
panel_roll.setText("Rol: "+String.format("%.1f", (180*info.roll/Math.PI))+"º");
if(panel_pitch != null)
panel_pitch.setText("Pitch: "+String.format("%.1f", (180*info.pitch/Math.PI))+"º");
if(panel_yaw != null)
panel_yaw.setText("Yaw: "+String.format("%.1f", (180*info.yaw/Math.PI))+"º");
}
}
});
//Log.d("Sim",System.currentTimeMillis()+": "+"post update gui 1");
}
Edit 2: I can actually remove the runOnUiThread since it is already at that thread, but the effect is the same, this is not the problem.
Edit 3: I tried to comment all the lines of the method updateHUD() and leave only these two:
if(panel_time != null)
panel_time.setText(info.time.replace("T", " "));
The effect is almost the same, if I touch any textView, the animation goes by steps like periodically freezing
Edit 4:
I noticed that the process inside the AsyncTask was taking longer than the available step time so it was never sleeping. I established a safe guard time of 10ms that is slept even if the simulation step is longer than the available time. So, I have minimum 10ms free of each 100ms. The efect stills the same. I am updating at 25Hz the browser and 1Hz a single textview text. If I disable the textview update, the webgl model animates smoothly. On the other hand, if I enable the textview update too, every time the text is updated, there are some miliseconds where the browser animation and its response to touches are blocked. This effect gets worst if I increase the task priority. I tried setting a huge guard of 500ms but the freezing effect stills appearing. I am using XWalkView, can it be something blocking the interaction of this view when UI Thread is acting?
I can't understand why a 4 core 2 RAMgb device needs way more time to compute the same simulation than in Linux or windows desktop PC. I have 25Hz-->40ms of available time and the steps take almost 70ms. In a PC I could keep the simulation at 25Hz in real time. Is there so much shit running in background in Android compared to other OS?
There must be another issue with your code. Try posting your AsyncTask in here.
You could also try something very basic like:
Create a new Thread that loops every 25Hz and update your UI by using the post() method of your UI elements or the runInUiThread() of your Activity. See if there's any code still running inside the UI Thread, that could do heavy work, that can be done outside the UI Thread.
I tried literally everything except for the most logic thing, trying the application without the debugger connected.
The reason to have slower simulation than in a PC, to freese UI events... all because the debugger takes a lot of resources from the device. So, I guess that from this point and avobe I will have to test the application without debugger, what forces me to reboot the phone each time to avoid the "waiting for debugger to connect".
Thank to all who tried.
I could be wrong, but I think that yours problem in synchronization on simulator.getSimulationResults() object. I can't see the realization of the simulator class and realization of the object returned by getSimulationResults(), but I suppose that getSimulationResults() returns the same object every time? If so, then it can be looks like this:
In the AsyncTaks call simulator.getSimulationResults().updateSimulation(...). If this method is synchronized, then this call will be lock the SimulationResults object for AsyncTaks thread.
updateSimulation(...) returns, and publishProgress() is called, but publishProgress() is only schedule the onProgressUpdate(Void... values) in the UI thread.
The new iteration in the AsyncTaks thread can be started befor the UI thread gets the control and executes onProgressUpdate(Void... values). So, AsyncTaks thread goes to the first step.
The UI thread gets the control and executes the onProgressUpdate(Void... values) and synchronized void updateHUD() methods, but updateHUD() can't be executed, because SimulationResults object is locked by the AsyncTaks thread in the updateSimulation(...) method. So the UI thread returns the control to the OS. This may occur many times.
So, onProgressUpdate(Void... values) method and all events in the UI thread can be executed only if the UI thread gets the control in the right moment when updateSimulation(...) method is not called in the AsyncTask thread.
You can check this idea by replacing the public synchronized void update HUD() on the public void update HUD(), and write something randomly in the TextView.
In any case, the use of AsyncTask in this case is not the best idea. AsyncTask's are executed in the TheadPool, but in the Android system this pool can consist from only one thread. So, all AsyncTask's will be executed one by one in the one thread.

Multiple simultaneous HTTP requests on Android

So, I have the code below inside an AsyncTask and want to call 7 different asynchronous HTTP requests. All works well, all the 7 execute() methods start at the same time (give a take a few millis, which is great).
Unfortunately, the time it takes with this method is aprox. 16 secs. If I exclude all executor stuff and call the HTTP download methods on the original worker Asynctask, it takes aprox. 9 secs. So, it actually takes less time in sequential order rather than concurrent. Any ideas why this is happening ? Maybe something on the server side ? Maybe because the executors were started on an Asynctask ? Thanks a lot !
MyExecutor executor = new MyExecutor(7, 7, 40000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
executor.execute(new Runnable()
{
#Override
public void run()
{
try {downloadSplashScreenJsonData();}
catch (Exception e)
{
Log.e(TAG, "Could not download splashscreen data.");
e.printStackTrace();
}
}
});
// after another 6 executor.execute() calls,
executor.shutdown();
executor.awaitTermination(40000, TimeUnit.MILLISECONDS);
class MyExecutor extends ThreadPoolExecutor
{
public MyExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
prestartAllCoreThreads();
// TODO Auto-generated constructor stub
}
#Override
public void execute(Runnable command) {
super.execute(command);
Log.e(TAG, "execute()");
Log.e(TAG, "no of thr: " + getActiveCount());
}
}
Don't know offhand, but I observe:
What is restartAllCoreThreads, and why are you calling it in a constructor? Don't start
threads before you need them (and a LinkedBlockingQueue<> will save you space).
Do you really need to run this in an AsyncTask? The threads in a Threadpool don't run on
the UI thread, and running off the UI thread is the main advantage of AsyncTask. If you
really want to do all of this in the background, use an IntentService.
As I look back on this matter, I want to add some more info.
First off, the use case that was required by the application was very retarded and cumbersome (but hey, clients, what can you do...). So like Joe stated above, I wouldn't download data on Asyncs in a million years now. One should use some sort of Service for downloading the data required, if possible.
Secondly, I ended up using RoboSpice library (it also provides caching) instead of Asyncs. It's still not as good as running on a Service, but it's much more well optimised than the barebone version. Might wanna check that out.

AsyncTask doesn't stop

I've created an AsyncTask that loads messaging history from a database and then shows it on the device screen:
private void loadHistoryFromDB(Date lastUpdateDate)
{
final class DBAsyncTask extends AsyncTask<Void, Void, List<XMPPMessage>>
{
#Override
protected List<XMPPMessage> doInBackground(Void... arg0)
{
List<XMPPMessage> messages = null;
try
{
messages = PersistenceManager.getXMPPMessagesFromDB(userInfo, 0, messagingActivity);
}
catch (SQLException e)
{
e.printStackTrace();
}
catch (LetsDatabaseException e)
{
e.printStackTrace();
}
return messages;
}
It seems to work fine, but after being executed, it leaves 2 running threads and I can't finish the activity because of that. How can I fix it?
As long as your tasks are executing properly (exits from onPostExecute), this shouldn't be something you have to worry about. Once executed, AsyncTask thread(s) will stick around for possible reuse in the form of a thread pool or single thread, depending on platform version. This is normal behaviour - they will eventually be cleaned-up/reused.
First off, make sure you are calling super.doInBackGround() at the top of your overridden method call.
If that isn't it, it's likely because you are maintaining the connecting to the database.
That is, you still have a lock established on the database.
See if you can explicitly unlock the database, that may fix your problem.
You could put it in the onPostExecute() method.
This problem is most likely due to confusion surrounding the cancel method of AsyncTask.
You need to break down your background task into loopable segments, then Before each loop iteration starts doing your task,you need to check if the task is cancelled and if it is you need to break the loop. There doesn't seem to be any other way to stop an AsyncTask from executing.
I've posted a detailed guide to this problem with code examples here:
http://tpbapp.com/android-development/android-asynctask-stop-running-cancel-method/

Categories

Resources