NetworkOnMainThreadException in AndroidAnnotations - android

I have a class annotated with #Rest and I use its methods in another with an instance of this, annotated with #RestService. When I call some method of the Rest client class, NetworkOnMainThreadException error appears. I thought that AndroidAnnotations managed the threading in these cases.

AndroidAnnotations does not make the implementation to use a background thread. Actually it should not have to, since it is uncertain whether the call is already on a background thread or not, etc. But you can easily put calls to a background thread with the #Background annotation. With the usage of that, you can simply avoid the AsyncTask boilerplate.

You are calling a RESTful web service, which is a network operation. As Android architecture says, network operation should be done on another thread than UI thread. For this you have to start another thread to do that operation, but the best practice is to use AsyncTask

The exception that is thrown when an application attempts to perform a networking operation on its main thread.
This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.
The most effecive way to create a worker thread for longer operations is with the AsyncTask class. Simply extend AsyncTask and implement the doInBackground() method to perform the work. To post progress changes to the user, you can call publishProgress(), which invokes the onProgressUpdate() callback method. From your implementation of onProgressUpdate() (which runs on the UI thread), you can notify the user. For example:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
// Do the long-running work in here
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
// This is called each time you call publishProgress()
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
// This is called when doInBackground() is finished
protected void onPostExecute(Long result) {
showNotification("Downloaded " + result + " bytes");
}
}
To execute this worker thread, simply create an instance and call execute():
new DownloadFilesTask().execute(url1, url2, url3);

Related

Android Activity UI Performance (AsyncTask while-loop)

How can I make this more efficient, at the moment it hangs the activity, giving the following information in logcat every time the while-loop completes I assume:
I/Choreographer: Skipped 55 frames! The application may be doing too much work on its
main thread.
Basically on a while-loop it reads a string variable, modifies and splits the string into parts which are then multiplied then divided, these final values are picked up by an interface which changes the custom UI element in the activity.
This seems too heavy on the main UI thread, I was under the impression that handler.post alleviates some of this by adding to the message queue however there are skipped frames.
I've tried to convert this code into an AsyncTask however I don't understand how this code can be converted to work in AsyncTask.
EDIT: AsyncTask custom class replacing old Thread while-loop.
(Old code for reference: http://pastebin.com/Dek6uQTE)
I'm still unsure how this fits in with AsyncTask, I have added the heavy code within the doInBackground() method however readBuf.replace and readBuf.split cannot be resolved. I thought to put the end changed in onProgressUpdate() as opposed to onPostExecute() as this would keep the UI elements updated automatically.
private class PostTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
readBuf = ((MyApplication) getApplication()).getReadBuf();
}
#Override
protected Void doInBackground(Void... readBuf) {
while (readBuf.length > 4) {
readBuf.replace("V", "");
String[] parts = readBuf.split(",");
String part1 = parts[0];
String part2 = parts[1];
speed1 = Float.parseFloat(part1);
speed2 = Float.parseFloat(part2);
finalspeed1 = (speed1 * 102) / div1;
finalspeed2 = (speed2 * 602) / div1;
publishProgress();
}
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
speedometer.onSpeedChanged(speedometer.getCurrentSpeed() - speedcur1);
speedometer.onSpeedChanged(speedometer.getCurrentSpeed() + finalspeed1);
speedometer1.onSpeedChanged(speedometer.getCurrentSpeed() - speedcur2);
speedometer1.onSpeedChanged(speedometer1.getCurrentSpeed() + finalspeed2);
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
You're starting a new thread which is actually just posting a new Runnable to the UI thread (handler is created on the UI thread), so it's not being done in the background. Here are a few tips to help with this:
If you are going to use a background thread to do the "work", then don't post a Runnable which is performing work to the handler, just post the result and update your UI accordingly.
Don't call findViewById() in a loop or any time after creation, if possible. Get a reference to the UI element and stash it off. This method is expensive as it does a search through your view hierarchy for the matching ID.
If you are going to use an AsyncTask just move the "work" part of your Runnable to the doInBackground() method and your UI updates into the onPostExecute() method.
Whether using a custom background Thread or AsyncTask, be sure to shutdown/cancel the work when your Activity leaves the run state, otherwise you will encounter problems as these components are not lifecycle aware.
It's not clear where readBuf is actually pulling data from, so this may also need some work. If this is real-time data coming from some other source, then you may need to have the custom Thread loop with a small yield. If using an AsyncTask, you'll have to create a new one each time as they are one-shot operations and not intended to be used as a long running background thread.
This article on AsyncTask has more details about how it works and pitfalls.

Stopping a thread in Android is deprecated

I am working on an Android project and I have a thread which is posting to a PHP API and does checks with the response.
Before the thread starts I show a progress dialog which can be cancelled. When the cancel is pressed I call thread.stop() but this shows up as deprecated.
Everything I have found on Google suggest that I have a flag and check the flag within the while loop and come out of the thread cleanly, however in my circumstances there is no loop, so how should I go about doing this?
The problem you are facing is know problem because, threads are not supposed to be stopped by calling thread.stop(); method.
Also Android discourages the use of Java Threads in Android, and Conveniently, Android has some additional support for when it comes to communicating between Threads, The Handler class provides a neat queued message mechanism, and Looper provides a handy method for processing same.
But as you mentioned you want to show a progress dialog which can be cancelled. When the cancel is pressed, so this type of functionality can be achieved using AsyncTask.
As AsyncTask is one of the easiest ways to implement parallelism in Android without having to deal with more complex methods like Threads.
Though it offers a basic level of parallelism with the UI thread, it should not be used for longer operations (of, say, not more than 2 seconds).
Mainly AsyncTask should handle your problem, Since:
It provides easy and standard recommended mechanism to publish background progress (see the Usage section here:
http://developer.android.com/reference/android/os/AsyncTask.html)
It provides method cancel(boolean); for cancelling a task(see the Cancelling a task section here:
http://developer.android.com/reference/android/os/AsyncTask.html
AsyncTask has four methods to do the task:
onPreExecute();
doInBackground();
onProgressUpdate();
onPostExecute();
And cancel(); method to handle the cancellation of the background work.
Where doInBackground() is the most important as it is where background computations are performed.
Code:
Here is a skeletal code outline with explanations:
public class AsyncTaskTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// This starts the AsyncTask
// Doesn't need to be in onCreate()
new DownloadFilesTask().execute(url1);
}
// Here is the AsyncTask class:
//
// AsyncTask<Params, Progress, Result>.
// Params – the type (Object/primitive) you pass to the AsyncTask from .execute()
// Progress – the type that gets passed to onProgressUpdate()
// Result – the type returns from doInBackground()
// Any of them can be String, Integer, Void, etc.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
}
For more in depth knowledge visit following links:
https://blog.nikitaog.me/2014/10/11/android-looper-handler-handlerthread-i/
http://developer.android.com/reference/android/os/AsyncTask.html

When to use AsyncTask and When to use Thread in Android

When to use AsyncTask and When to use Thread as both do work in background and both can manipulate controls in UI Thread by some mechanism..
May this help you:
For long-running tasks, we use Java threads, and Android's native AsyncTask.
Basically Use AsyncTask for:
Simple network operations which do not require downloading a lot of data
Disk-bound tasks that might take more than a few milliseconds
And Use Java threads for:
Network operations which involve moderate to large amounts of data (either uploading or downloading)
High-CPU tasks which need to be run in the background
Any task where you want to control the CPU usage relative to the GUI thread
For more information refer
Mohit's answer Click Here
Edit:
Service is like an Activity but has no interface. Probably if you want to fetch the weather for example you won't create a blank activity for it, for this you will use a Service. Service is access to a Context object which has an independent life cycle. This allows for reuse of common code by many activities and, in the case of public or exposed services in many applications.
A Service runs on the main thread of the calling Component’s process by default (and hence can degrade responsiveness and cause ANRs), hence you should create a new Thread to perform long running operations.
A Thread is a Thread, probably you already know it from other part. You need to know that you cannot update UI from a Thread. You need to use a Handler for this and stopping a thread sometime become problematic also. A thread is a mechanism for doing work without blocking other work...
A service does not imply a thread and a thread does not imply a service. Both are different from eachother..
An AsyncTask is an intelligent Thread that is advised to be used. Intelligent as it can help with it's methods, and there are two methods that run on UI thread, which is good to update UI components.
AsyncTask is just a "helper" class provided with Android SDK to make it easier to skip to the UI thread after the background task is finished. It is built over the standard Java threading API. It does not give antyhing that cannot be done with Threads only. It addresses the common scenario of switching between the short task run background thread and UI thread.
Generally it is convenient to use AsyncTask when you must "skip back" to UI thread when the background task is done or when you have to give some feedback to UI thread during task execution. Otherwise it's just overhead.
You are not forced to use AsyncTask. If you as a developer prefer using Threads directly or Futures you may use it and skip to UI thread on your own manually after the background task is done.
EDIT:
Some other answers here suggest that using AsyncTask should be limited to short tasks. Allegedly because it uses a common pool. However it is no longer true since API Level 11 (so, for quite a long time). You can use executeOnExecutor instead of execute to execute AsyncTask's in dedicated thread pool. See http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor%28java.util.concurrent.Executor,%20Params...%29
Because examples are usually more communicative look at the example below.
Let's assume that we have a static function to do some heavy task and a TextView which we want to display progress and final status of the task declared as below:
static Object doHeavyTask(String string) throws Exception;
TextView progressInfo;
Execution of the task in background thread using async task would look like:
new AsyncTask<String, Integer, Exception>() {
#Override
protected Exception doInBackground(String... params) {
for (int i = 0; i < params.length; i++) {
try {
doHeavyTask(params[i]);
} catch (Exception e) {
return e;
}
publishProgress(i, params.length);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
progressInfo.setText("Executed " + values[0] +
" of " + values[1] + " tasks.");
}
#Override
protected void onPostExecute(Exception result) {
if (result == null) {
progressInfo.setText("Heavy background job done successfully!");
}
else {
progressInfo.setText("Heavy background job failed!" +
"Exception message: " + result.getMessage());
}
}
}.execute("input1", "input2", "input3");
Exactly the same can be achieved with Thread:
final Handler handler = new Handler(Looper.getMainLooper());
final String[] params = { "input1", "input2", "input3" };
new Thread() {
#Override
public void run() {
for (int i = 0; i < params.length; i++) {
try {
doHeavyTask(params[i]);
} catch (final Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
progressInfo.setText("Heavy background job failed!" +
"Exception message: " + e.getMessage());
}
});
return;
}
final int currentIndex = i;
handler.post(new Runnable() {
#Override
public void run() {
progressInfo.setText("Executed " + currentIndex +
" of " + params.length + " tasks.");
}
});
}
handler.post(new Runnable() {
#Override
public void run() {
progressInfo.setText(
"Heavy background job done successfully!");
}
});
}
}.start();
As you see above using the AsyncTask is simply a bit more convenient. But there is no other advantage, just this convenience :).
If you prepared your own task encapsulating Thread (and a Handler to skip back to the UI thread) then maybe your class will be more efficient/comfortable for you to use.
That's all :).
You can run multiple threads concurrently. But asynctask is queued, meaning it is running one task at a time.

AsyncTask Not Updating on UI thread

I have an AsyncTask updating an ActionBarSherlock progress implementation. Somehow the onProgressUpdate is throwing a threading error though it claims to execute on the UI thread.
protected void onProgressUpdate(Integer... values)
{
setSupportProgress(values[0]);
}
The error is:
03-06 00:13:11.672: E/AndroidRuntime(4183): at com.anthonymandra.framework.GalleryActivity$ShareTask.onProgressUpdate(GalleryActivity.java:476)
Only the original thread that created a view hierarchy can touch its
views.
As far as I can tell I should be accessing the UI thread for this...
I have many working AsyncTasks in my app, but as requested here's the doInBackground (simplified):
for (MediaObject image : toShare)
{
BufferedInputStream imageData = image.getThumbStream();
File swapFile = getSwapFile(...);
write(swapFile, imageData);
++completed;
float progress = (float) completed / toShare.size();
int progressLocation = (int) Math.ceil(progressRange * progress);
onProgressUpdate(progressLocation);
}
Okay so the problem is you are calling onProgressUpdate when you should call publishProgress. The OP figured out this himself/herself so I just copy pasted it so he/she does not need to wait to accept the answer. Below is information how AsyncTasks works and it is good knowledge.
Are you creating the AsyncTask on the UI thread? If you are not that is the problem. onProgressUpdate will be run on the thread that created the AsyncTask.
Update: Let us have some code digging time (API 15 source code)!
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
This fellow will call it's static Handler sHandler. The documentation says:
When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
Thanks to Bruno Mateus with his documentation look-up skills:
Look that, i found at documentation page: Threading rules - There are
a few threading rules that must be followed for this class to work
properly: - The AsyncTask class must be loaded on the UI thread. This
is done automatically as of JELLY_BEAN. - The task instance must be
created on the UI thread. execute(Params...) must be invoked on the UI
thread. - Do not call onPreExecute(), onPostExecute(Result),
doInBackground(Params...), onProgressUpdate(Progress...) manually. -
The task can be executed only once (an exception will be thrown if a
second execution is attempted.)
You can declare your AsyncTask as a innerclass of your activity like that:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}
private class DownloadImageTask extends AsyncTask {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
I was manually calling:
onProgressUpdate
You should call
publishProgress
Easy mistake, but great info. Simon and Bruno deserve the credit, post the answer if you like. Thanks for the fast and extensive response!

Async Task Memory Cleanup

I am having a bit of trouble with how to cleanup the memory used in my AsyncTask when the user forces the application to quit or go to the background.
Specifically, I have an app that is using an AsyncTask to record audio data and graph the signal in realtime. For the recording I am using the AudioRecord class, which requires you to start a recording, and then stop and release the recording object. My problem is that I do not know how to stop and release this object.
Options I have thought about and tried:
Stopping the releasing the object in the onPause, onStop, and onDestroy methods, but this causes an exception.
Stopping and releasing the object in the onPostExecute method of AsyncTask. The problem with this is I am not sure if this method is ever called when the user force quits the app, since the doInBackground method is never finished. I have not been able to find any documentation concerning this.
My AsyncTask looks as follows:
AsyncTask<Void, Void, Void> drawer = new AsyncTask<Void, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
recorder.startRecording();
}
#Override
protected Void doInBackground(Void... arg0) {
while(true) {
int nRead = 0;
int offset = 0;
while(nRead != readSize) {
nRead += recorder.read(buffer, offset + nRead, readSize - nRead);
}
for(int i = 0; i < readSize; i++) {
data[i] = buffer[i];
}
publishProgress();
}
}
#Override
protected void onProgressUpdate(Void... arg0) {
view.setData(data);
view.invalidate();
}
};
The code works great, I am just unsure the best way to make sure I properly clean up the recording object and don't leak at all. My confusion is just as to what happens to an AsyncTask when the UI Thread is paused or stops, and additionally, if you are able to stop an AudioRecord Object from a different Thread you stared it.
Any help would be greatly appreciated.
Thank you,
OnPostExecute will not be called because you never finish your background loop. You need to have a condition on which you exit your loop. You can have a variable you set in the UI and then check in the background task, or use the ability to cancel AsyncTask.
For example, in your onPause() method, you can cancel the task with drawer.cancel(true);
Then, in your doInBackground loop, check to see if the task has been cancelled.
if (isCancelled()) {
// clean up here
break;
} else {
publishProgress();
}
This works as long as you do not need to touch the UI for clean up. If you need to do UI clean up, then you can override the onCancelled method.
Note, for long running tasks, it is recommended that you do not use AsyncTask. So you may want to look into using threads. From AsyncTask documentation,
AsyncTasks should ideally be used for short operations (a few seconds
at the most.) If you need to keep threads running for long periods of
time, it is highly recommended you use the various APIs provided by
the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor
and FutureTask.

Categories

Resources