I have an Android application that uses AsyncTasks to make get and post calls to send and retrieve data from server. All works fine but sometimes the async task takes a lot of time to execute and thus other async tasks have to wait (if more than 5 async tasks is there) so what will be the best alternative or how to increase the thread pool if it is safe to do so.
Asynctask are implemented behind the scene using threadpool, the default pool size for asynctasks is 1(so you can't run 2 asynctasks in parallel).
In newer versions of android the default Asynctask pool size is 5.
It's possible to change it but not recommended.
You can just create thread like in the sample I attached before:
Thread thread = new Thread() {
#Override
public void run() {
try {
//Do http request here
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
Related
This is my first Android application and I am finding troubles with while loop, I am trying to use a while loop on my Android application but the application freezes.
What I'm trying to do is track the user location (using onlocationChanged) and keep querying on the location until the query returns a result. It's a GIS application so I am going to describe the application behavior:
the application keeps tracking the user position using a listener "onLocationChangedListener" and store it in a variable "myPosition". I am using a boolean"noResults=true". I will use a method "query(myPosition)" in the while loop, this method has a callback that when a result is found, and changes a boolean "noResults" to false. the loop will keep on until "noResults" is false (that means query's callback changed the boolean's value)
, here's what I did:
while(noResults)
{
//myPosition keeps changing
query(myPosition);
//query has a callback that when a result is found it changes noResults to false
}
I resolved the problem using a "Handler" that query the Feature Layer every 5 seconds, this stops the main thread from generating application not responding error:
Handler m_handler=new Handler();
Runnable m_runnable;
m_runnable = new Runnable(){
public void run() {
//query code here
m_handler.postDelayed(m_runnable, 5000);
}
};
m_handler.postDelayed(m_runnable, 0);
running while loop codes on the main thread freezes the UI, and makes all other processes pause making your app unresponsive use
Threads..
also note that the while loop you are running is running on a default Thread termed as the ui thread so in short run while loops on separate threads..
eg..
new Thread(new Runnable() {
#Override
public void run() {
// Your hard while loop here
//get whatever you want and update your ui with ui communication methods.
}
).start();
for ui communicating methods
View.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), "updated ui", Toast.LENGTH_LONG).show();
}
});
the view could be any views you are updating..
also like #TehCoder said you could use asynctask but asynctask is not meant for long workaflow work there are 3 of them but i can't recall the last one
Maybe you should use an AsyncTask? I'm not quite sure what your problem is tho.
Loop is not a problem in android (or any language).
There are two scenario might be reason for your freezing,
If you run network call in api, android throw error and crashes. You have to do network related calls in Aysnc Task ot threading
Use try throw catch and exception cases to avoid app crashing and better coding skill.
an Android 4+ app should perform a long running operation. This could be copying a million files from A to B for example. To not block the UI this operation runs in the background using an AsyncTask.
Assume that the operation needs some user feedback in the middle of the process to continue its work, e.g. "File XY already exists. Override, Irgnore or Rename?"
What is the best way to get this feedback from the user? Since the operation is running in a background thread one could not just present an AlertDialog (or something similar) since UI interaction is only possible in the main thread...
So for I came across these solution:
Ask for feeback before background threads starts, e.g. ask how to handle conflicts before starting to copy/move the files in the
background.
Do not handle conflicts but note them to ask the user
how to handle them after the operation is complete in a new
operation.
End the background operation on the first conflict, ask the user for feedback and continue a new background operation
I do not like any of these solutions. In the first case the user is asked for feedback even if there will be no conflict at all. The second solutions is not possible if the steps have to be processed in a specific order. The third solution would result in code that is very difficult to read/understand/maintain.
A good solution would be:
Stop the background thread
Marshal to the UI thread and get feedback from the user
Resume background thread and use feedback to continue the operation
Using GCD in Objectiv-C/iOS or async/await in C# this is not a big problem. But how can this be done in Android using AsyncTask?
Meanwhile I thought, that I found an answer here: Simply run myActivity.runOnUiThread(...) within doInBackground(...) and wait for it. Sounds good, but it does not work. The AsyncTask/background thread does NOT wait for the Runnable to finish:
private void copyFiles() {
CopyTask copyTask = new CopyTask (this);
copyTask.execute();
}
private class CopyTask extends CustomAsyncTask<Void, Void, Void> {
private doCopy;
#Override
protected Boolean doInBackground(Void... params) {
// Custom code, e.g. copy files from A to B and check for conflict
for (File file : allFiles) {
doCopy = true;
if (isConflict(file)) {
// Stop current thread and ask for user feedback on UI Thread
Runnable uiRunnable = new Runnable() {
public void run() {
// Pos 1. --> Execute custom code, e.g. use AlertDialog to ask user if file should be replaced...
doCopy = false;
synchronized (this) {
this.notify();
}
}
});
synchronized(uiRunnable) {
// Execute code on UI thread
activity.runOnUiThread(uiRunnable);
// Wait until runnable finished
try {
uiRunnable.wait();
}
catch (InterruptedException e ) {
e.printStackTrace();
}
}
}
// Pos 2. --> Continue work
if (doCopy)
copyFromAToB(File);
}
return null;
}
}
I would expect, that when a conflict is detected the Runnable is executed and and Pos 1 (code inside Runnable to resolve conflict) is executed BEVOR Pos 2 is reached. This is not the case. The Runnable is executed correctly but the AsyncTask does not wait for it to finish. The execution of doInBackground is continued without any interruption. It seems that doInBackground and the Runnable are executed in parallel (not suprising since they are executed on different threads) but why does doInBackground not wait?
Is it fine to do following if we think about efficiency?
new Runnable() {
#Override
public void run() {
try {
final Runnable uitask = new Runnable() {
public void run() {
//sth that modifies UI
}
};
for (...) {
context.runOnUiThread(uitask);
Thread.sleep(...);
}
} catch (Throwable t) {
}
}
}
I'm most concerned about that runOnUi might create new thread each time, which would be very bad? Am I right or it smarter like ThreadPool?
Well, runOnUiThread doesn't create new threads, it is starting your runnable on the existing UI thread.
but instead of your code you could just do
void onCreate(..) {
...
mHandler = new Handler();
}
for (...) {
mHandler.postDelayed(uitask, DELAY * i++);
}
I'm most concerned about that runOnUi might create new thread each
time, which would be very bad?
Well. It depends what you want to achieve. In Android, native threads are not much efficient. There are more effective ways how to do background work (SDK provides them).
If you want to do some periodical work you can use Handler to achieve your goal. Just create only one Runnable and then you can send request for periodical callbacks. Another solution is to use Services which run in background. They're directly designated for long-running tasks and provide very handy way for background processing.
Sometimes you need to inform user with some information about current progress in your tasks so in this case you can simply use mentioned Handler or AsyncTask.
I think your solution is not clean and efficient. If you'll create for example 40 Threads, your work won't be faster or more efficient at all. Your GB will scream and application will take the greater part of CPU and high battery consumption is something you shouldn't allow.
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.
I'm kinda new to android development, but i'm trying to make a xml parser. I've been using android.sax library, following some tutos, and this works great.
One thing that is making me sceptical, is that I don't actually launch the parser in a separate thread, I just use a handlers to communicate between my parser and my main activity.
Should I parse in a Thread ?
Here's my main activity code :
tv = (TextView)findViewById(R.id.tv);
try {
URL url = new URL("https://www.googleapis.com/shopping/search/v1/public/products?key=AAAAABBBBBCCCCDDDEEEEFFF&country=FR&restrictBy=gtin=5030999075254&alt=atom");
XMLHandler xHandler = new XMLHandler();
Feed feed = xHandler.parse(url.openStream());
if(feed.getTotalResults()==0 || feed.getItems() == null || feed.getItems().isEmpty()) {
Log.w("XMLPARSENull", "No items
}
else {
tv.setText(feed.getTotalResults()+" " + feed.getItemsPerPage() + " " + feed.getStartIndex() + " " + feed.getTitle());
Iterator<Product> it = feed.getItems().iterator();
while(it.hasNext()) {
Log.w("XMLPARSEFeed",it.next().getName());
}
}
} catch(Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("XMLPARSEException", "ERROR",e);
}
I don't think that it's the parsing so much as the network operation, as any network request should not be performed in the UI thread. You can either spawn a new Thread or an AsyncTask to perform your network request. Here are some links to help:
AsyncTask
Painless threading
Expensive operations
Designing for responsiveness
Thread documentation
Handler documentation
A simple answer:
If you have connections in your main ( UI ) thread, the user interface will become frozen whilst the thread is used to download the information and parse it. It takes some time for a connection so it may appear to freeze.
Apart from that, android 4.0 now does not actually allow you to call HTTP requests from this thread, it will throw an error which will be seen in logcat before crashing.
It is best practise to use an Async Task here, here is some more information on that.
Information on Async Tasks!
Yes, it is imperative that you move your parsing into a background thread, particularly if your XML is being streamed across the network; otherwise your app is likely to be killed off by the system for blocking the main thread.
You don't have to use a raw Thread, though; Android provides things like ASyncTask to make it a bit easier.
Everything which isn't related to direct interaction with GUI should be moved to separate thread, prefferably AsyncTask if you need interaction with GUI from that thread since Android won't allow accessing GUI from regular Thread class.
http://developer.android.com/reference/android/os/AsyncTask.html