I am reviewing/cleaning up some Android code. The code did some "asynchronous" network and data operations using this pattern:
new Thread() { public void run() { { ... runOnUiThread( { .. } ) }
A lot. With all the ugly consequences (no error checks, Sleeps, boolean finish variables...).
Till now, I ended up using (few) AsyncTasks and (more) Loaders as replacements.
Now I have stumbled upon a couple of "fire-and-forget" network communications: the code (currently, a Thread, as always) calls a web service posting some data.
I do not need to know if the data was received, and I do not need to know if there was any error.
Which is the best way of doing this? A Runnable or AsyncTask (static nested class, so I do not "leak" a reference to "this" activity?)
Or is there something better (more "lightweight" and cleaner?)
If you don't need to know when task execution is finished then you definitely don't need AsyncTask at all. Therefore the most lightweight solution is just a Thread. You can use Executor which will create threads for you. To get rid of nested classes you could predefine tasks. Sample:
Predefined task:
public static class TaskA implements Runnable{
private int someParam;
public TaskA(int someParam) {
this.someParam = someParam;
}
#Override
public void run() {
//
}
}
Static Executor
public static class FireAndForgetExecutor{
private static Executor executor = Executors.newFixedThreadPool(5);
public static void exec(Runnable command){
executor.execute(command);
}
}
And usage:
FireAndForgetExecutor.exec(new TaskA(10));
PS don't forget that a Thread is connected to the GC root! So if you pass heavy object like an activity or a bitmap into the task it could lead to memory leak.
Related
I'm using a weak reference inside a static Handler to avoid memory leaks, however, sometimes this reference is being nullified, I cannot understand why.
The static handler is defined inside a repository class that has a method to perform an operation in the background, receives a callback to notify the caller when it's done:
public class MyRepository {
public void performOperation(ContentResolver cr, RepositoryCallback callback) {
MyHandler handler = new MyHandler(cr, callback);
handler.startQuery(...)
}
interface RepositoryCallback {
void onSuccess(MyModel model);
}
// Handler class code here
}
The code of the handler is the following:
private static class MyHandler extends AsyncQueryHandler {
private final WeakReference<RepositoryCallback> weakCallback;
public MyHandler(ContentResolver cr, RepositoryCallback callback) {
super(cr);
this.weakCallback = new WeakReference<>(callback);
}
#Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
RepositoryCallback callback = this.weakCallback.get();
if (callback != null) { // --> Here sometimes it is null
// Do some stuff with the cursor to create MyModel
callback.onSuccess(model);
}
}
}
For some reason, this.weakCallback.get() sometimes is null, and I'm trying to understand why.
The activity code looks like this:
public class MyActivity extends AppCompatActivity {
public void loadModel() {
showLoadingView();
myRepository.performOperation(context.getContentResolver(), new RepositoryCallback() {
#Override
public void onSuccess(MyModel model) {
hideLoadingView();
// Do something with model
}
});
}
}
As you can see I'm creating an anonymous class for the callback, but nobody is holding a reference to it.
Is this the cause of the weak reference being nullified?
Thanks.
That's the "classical" bug associated with weak references.
If the Observable holds the only reference to the Observer, and this reference is weak, then it can be cleared and Observer be garbage collected.
Since you're using anonymous class, Observable will hold the only reference to it, therefore it will be cleared.
As a side note - in my entire experience of Android development, whenever I saw devs using weak references, it always was a code smell. Usually it indicates that either devs don't understand how weak references work, or they don't trust their own code.
A good rule of thumb is that you should never use weak references.
EDIT:
I think that Handler is an anti-pattern in general. You can read more about this in this Reddit thread. There is also a thread there in which I helped one dev to see how he can get rid of HandlerThread in his codebase.
On the other hand, Jake Wharton disagreed with my statements.
Take what you'd like from there, but, in general, I would say that having a static Handler is anti-pattern for sure.
If you are worried about AndroidStudion warnings, then just remember that Google are responsible for AsyncTask and Loaders. This warning is not just useless, but actually bad. They should've made it you should not use static Hadlers.
If all you need is to offload work to BG thread and then get a callback on UI thread then you would be much better off with something like RxJava. Or even the evil AsyncTask.
I guess you're using AsyncQueryHandler in order to access ContentProvider. This is too a very controversial approach. If you don't need to share data with other apps, you might be better off by using some ORM that handles the multithreading for you.
I am using an AsyncTask to download a database with a progressdialog that shows progress on the UI. Some of my users are receiving the error:
CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
As I understand it, this should only happen if you are trying to update Views off of the UI thread. Here is the error:
com...updateops.DbCreate.onProgressUpdate(DbCreate.java:70)
at com...updateops.DbCreate.onProgressUpdate(DbCreate.java:1)
and here is my code:
public class DbCreate extends AsyncTask<String, String, String>{
private static Context mCtx;
private static ProgressDialog mDialog;
public static AmazonSimpleDBClient mSDbClient;
public static AmazonS3Client mS3Client;
private static int mAppVersion;
private static boolean mCreate;
public DbCreate(Context ctx, int versionCode, boolean create) {
mCtx = ctx.getApplicationContext();
mAppVersion = versionCode;
mDialog = new ProgressDialog(ctx);
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setMessage("Checking for server access. Please wait...");
mDialog.setCancelable(false);
mDialog.setMax(1);
mDialog.show();
mCreate = create;
}
protected void onProgressUpdate(String... name) {
if (name[0].equals("item")) {
mDialog.incrementProgressBy(1);
} else if (name[0].equals("setMax")) {
mDialog.setProgress(0);
mDialog.setMax(Integer.parseInt(name[1])); <-- This is line 70
}}
#Override
protected String doInBackground(String... arg0) {
**do stuff**
publishProgress("setMax", ""+ 3);
}
It looks to me like I am following exactly what I am supposed to do in order to avoid this error. Anyone know why it's happening?
Edit: I should also mention that this code works most of the time. I am receiving crash reports on the Developer Console.
According to the onProgressUpdate(Progress...) is invoked on the UI thread after a call to publishProgress(Progress...).
You should analyze the whole log report to check if there is any chance that your async task was created on other thread.
And if you really cannot find the root cause you can use a handler created on UI thread to workaround.
You code looks fine and in most of the cases it should work. I would suggest you to use handler. You can write a handler in UI thread and call it from onProgressUpdate(). This will completely ensure that the UI work is done in UI thread.
This will fix your issue for sure, but I dont know why you are gettin error at first hand. I have seen this kind of issue before and never got a concrete reason for it.
I had the same problem that you are describing and I fixed it by using a runOnUiThread() call against the context owned by the AsyncTask (as you also have in your example).
The following solution should absolve your issues;
#Override
protected void onProgressUpdate(final String... messages){
myActivityReference.runOnUiThread(new Runnable() {
#Override
public void run() {
// Your UI changes here.
}
});
}
It's worth noting that my AsyncTask was originally called from within a AlertDialog, which is what I believe is causing the issue to begin with.
I found the same issue on Android 2.3.x devices and here's the crash log:
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:2934)
...
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.os.HandlerThread.run(HandlerThread.java:60)
The log indicates that onProgressUpdate and onPostExecute are executed on HandlerThread which is essentially a worker thread with a custom Looper. So that's why the crash occurs.
Therefore, in your case it is likely the internal handler of AsyncTask is bound to non main looper associated with a worker thread like HandlerThread and onUpdateProgress is processed on worker thread instead.
I found this bug appear pervasively on Android 2.3 devices. Therefore I checked the source code of AsyncTask in 2.3 and found this:
private static final InternalHandler sHandler = new InternalHandler();
private static class InternalHandler extends Handler {
#SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
#Override
public void handleMessage(Message msg) {
...
}
}
The chance is that the internal handler might be bound to a non main looper.
I also checked the latest source code of AsyncTask and saw the change:
private static class InternalHandler extends Handler {
public InternalHandler() {
super(Looper.getMainLooper());
}
...
}
The InternalHandler constructor eliminate the chance that it might be bound to a non main looper therefore onUpdateProgress behaves normal on post Android 2.3 devices.
Hello i am new to android and android thread so want to know that
How could we use more number of thread in order to perform every single task or method so that while user click on any UI component it does effect the performance ,having little knowledge of how the handler thread and asynctask work.But how can we run every method inside the asynctask so to do the operation and mean while user can do the other operation also.
In the application
i have voice recording from mic.
next showing progress bar.
next showing gallery with some image and with that setting effect to the picture.
The recommended way is to use AsyncTasks for long running tasks. So, not everything needs to be run with AsyncTasks, as you can get a performance hit due to the context switching.
As for how AsyncTasks work, read the documentation.
Use an AsyncTask and make sure to implement these as needed. You mention the idea of doing something in the background while a user is doing something so I'm guessing you'll want to alter the UI.
Take a look at these links for an more details from Android. They cover Runnable, AsyncTask and Handler
Overview of them all http://developer.android.com/guide/components/processes-and-threads.html
AsyncTask example http://developer.android.com/reference/android/os/AsyncTask.html
Old but relevant, Painless Threading http://android-developers.blogspot.com/2009/05/painless-threading.html
Another, more complex example http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
I don't generally paste full examples in here but I had a lot of trouble finding an example I was happy with for a long time and to help you and others, here is my preferred method. I generally use an AsyncTask with a callback to the Activity that started the task.
In this example, I'm pretending that a user has triggered onClick(...) such as with a button, but could be anything that triggers a call into the Activity.
// Within your Activity, call a custom AsyncTask such as MyTask
public class MyActivity extends Activity implements View.OnClickListener, MyTask.OnTaskComplete {
//...
public void onClick(View v) {
// For example, thet user clicked a button
// get data via your task
// using `this` will tell the MyTask object to use this Activty
// for the listener
MyTask task = new MyTask(this);
task.execute(); // data returned in callback below
}
public void onTaskComplete(MyObject obj) {
// After the AsyncTask completes, it calls this callback.
// use your data here
mTextBox.setText(obj.getName);
}
}
Getting the data out of a task can be done many ways, but I prefer an interface such as OnTaskComplete that is implemented above and triggered below.
The main idea here is that I often want to keep away from inner classes as they become more complex. Mostly a personal preference, but it allows me to separate reusable tasks outside of one class.
public class MyTask extends AsyncTask<Void, Void, MyObject> {
public static interface OnTaskComplete {
public abstract void onTaskComplete(MyObject obj);
}
static final String TAG = "MyTask";
private OnTaskComplete mListener;
public MyTask(OnTaskComplete listener) {
Log.d(TAG, "new MyTask");
if (listener == null)
throw new NullPointerException("Listener may not be null");
this.mListener = listener;
}
#Override
protected MyObject doInBackground(Void... unused) {
Log.d(TAG, "doInBackground");
// do background tasks
MyObbject obj = new MyObject();
// Do long running tasks here to not block the UI
obj.populateData();
return
}
#Override
protected void onPostExecute(MyObject obj) {
Log.d(TAG, "onPostExecute");
this.mListener.onTaskComplete(obj);
}
}
I'm using AsyncTask class to execute WS methods. I would like to have a generic async task class to call any method in the WS.
I create a set of classes that works fine but the problem is when I have to update the UI. I know I can create the async task with a reference to the Activity class and then execute the desired method, but what I want is the method to execute to be also a parameter.
Otherwise I have to implement a new class for each method which interacts with the UI because each action is different depending on the method.
Provably the solution is to use Listeners combined with parameters but I didn't find a complete example of how to use this.
In Java, you cannot pass a method as a parameter, but you can pass an object that extends or implements an ancestor and overrides that method. The Command pattern uses this concept (http://en.wikipedia.org/wiki/Command_pattern).
Here's an idea of the approach:
private static interface Command {
public void execute();
}
public static final class MyWsCommand1 implements Command {
#Override
public void execute() {
// TODO your WS code 1
}
}
public static final class MyWsCommand2 implements Command {
#Override
public void execute() {
// TODO your WS code 2
}
}
private static class GenericAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private Command command;
public GenericAsyncTask(Command command) {
super();
this.command = command;
}
#Override
protected Result doInBackground(Params... params) {
// TODO your code
command.execute();
// TODO your code
return null;
}
}
private GenericAsyncTask<Object, Object, Object> myAsyncTask1;
private GenericAsyncTask<Object, Object, Object> myAsyncTask2;
And use those in your code:
myAsyncTask1 = new GenericAsyncTask<Object, Object, Object>(new MyWsCommand1());
myAsyncTask1.execute();
...
myAsyncTask2 = new GenericAsyncTask<Object, Object, Object>(new MyWsCommand2());
myAsyncTask2.execute();
by WS , you mean webservice?
asyncTask is not meant to be used for such long tasks . they are supposed to do small tasks . things that take (approx.) less than 5 seconds .
if you wish to do very long tasks , use a simple thread and consider putting it in a service.
also , in order to communicate with it , you can communicate with the service , and when you need to post something to the UI thread , use a handler .
The most close answer is this
You can choose the method in the same UI which waits until the background process ends
I would use Async, and I did on a production implementation. The issue you'll run into is doing more logic in the doInBackground because if you watch your debug build any time you see it say "Skipped X Frames" you may want to do a lot of post processing in doInBackground still.
Using an interface is the best approach, it's how I implemented my Async class. full.stack.ex hit the nail on the head with that answer. That answer shows a clear, simple, powerful way to extend Async and use it for your purpose.
I have Activity class, Controller class (normal java class use to control number of activity) and BusinessEngine class (normal java class use to process data).
When I need to do some calculation from activity, Activity will call Controller and Controller will call BusinessEngine to do the calculation. When BusinessEngine done with the calculation, it will pass the value back to Controller and finally let the activity know the calculation is complete.
The problem is how I callback Activity from Controller class? Or pass any data to Activity and notify it the data has been change?
Any "long" running tasks must be performed in a background thread. I'm not sure if your currently doing this for your task, so just in case your not, there are a couple of ways to do this. The first is to simply use a AsyncTask, the second is to create your own instance of AbstractExecutorService (AsyncTask uses ThreadPoolExecutor) and use that to post Runnable or Callables to. The later way may save you a lot of re factoring depending on your code base.
Assuming you're now running the task in a background thread, it's necessary to perform your UI updates on the UI thread. There are again a couple of ways to do this. One method is to post a runnable to the method Activity#runOnUiThread, the second is to use a Handler which has previously been created on the UI thread (which Activity#runOnUiThread does behind the scenes).
So, assume your Activity has a method #postResults(final Object o), and your controller has the method #doSomething(final Activity activity).
Your activity would look something like this.
public class MyActivity extends Activity {
Controller controller = ....
ExecutorService service = Executors.newFixedThreadPool(10);
private void startTask() {
Runnable r = new Runnable() {
public void run() {
c.doSomething(MyActivity.this);
}
}
service.submit(r);
}
public void postResults(final Object o) {
Runnable r = new Runnable() {
public void run() {
// Update your UI here
}
}
runOnUiThread(r)
}
}
and your controller
public class Controller {
public void doSomething(final Activity activity) {
// Perform some long running task here
activity.postResults(someObject);
}
}
Obviously this example could be tidied up (for example passing a interface to doSomething rather than the Activity), but hopefully it should be enough to understand what you need to do :)
Why are you looking for the controller to call you Activity? Normally, your Activity must call the controller via its methods and directly get results from them:
// Code in your Activity
result = controller.doSomething(args);
try using a android AsyncTask, if your method takes a long time to process. example
Add your classes to an Async task or if you're calling the classes and passing them from one class to the other.I would say to use static class. And provide some code so we can know how you are passing your data.
If not use general methods to call the superclass or the subclass.
My answer is a bit abstract as information is less.