Code in OnCreate isn't being run in order - java

I am not writing my whole code, I have the following simple structure:
public class CreateEventActivity extends ActionBarActivity{
int x;
void onCreate(){
new AsyncTask1().execute();//here I change the value of x
Log.i("000000",String.valueOf(x));
}
public AsyncTask1 extends AsyncTask<Void, Void ,Void>{
// process include changing the vlaue of x to 4
Log.i("111111",String.valueOf(x));
}
}
in the log: the log with the tag 000000 appears before the log with tag 111111 what's going on?
First I thought the problem was because I am chainging the value of x in onPostExecute so I did so in doInBackground and the problem still the same.

what's going on?
AsyncTask is asynchronous. Quoting the documentation:
This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
The reason that you use an AsyncTask is to do work in a background thread (e.g., download some data), followed by some work on the main application thread (e.g., update the UI based upon that data).
is there anyway to avoid this?
Get rid of the AsyncTask, or learn how to use it properly. Among other things:
Do not modify the same data in multiple threads without appropriate synchronization logic
Do not try to fork a background thread, then block the main application thread (which appears to be what you want), as that eliminates the entire point of the background thread in the first place
If you have work that you want to do when doInBackground() ends, put that work in onPostExecute(), not in statements that follow your execute() or executeOnExecutor() call.

That's the nature of an Async task.
Async Tasks are mostly being used for long running operations; like webcalls, I/O operations and so on as they can take a while.
If you want to have a callback when the AsyncTask finishes you can override the OnPostExecute() method

Related

Android: How to show a spinner while performing a long-running operation?

I have a ProgressBar in .xml that I want to show when a long-running operation. I use
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);
to set its visibility in some onButtonClick method. If the above code is all that is in the method, it works just fine. The problem is when I have a method like this:
public void onButtonClick (android.view.View view){
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);
longRunningMethod(); // This method takes 5-10 seconds to run
progressSpinner.setVisibility(View.GONE);
}
The UI just locks up until longRunningMethod is done. That method works just fine, but the spinner never shows.
I tried running everything on a different thread with this:
public void onButtonClick (android.view.View view){
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(this::longRunningMethod);
}
And I added the spinner visibility changing stuff to longRunningMethod:
private void longRunningMethod(){
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);
// Logic that takes 5-10 seconds to run.
progressSpinner.setVisibility(View.GONE);
}
When I do this, the UI doesn't lock up, but nothing in longRunningMethod works. The spinner won't show and the logic also doesn't seem to work, although this may just be a problem with that logic not playing nice on not-the-UI-thread. I am very confused that the spinner visibility won't update from here though.
For running long task operations, you should use Worker Thread.
You must run your task in worker thread and then return task results to UI.
First method is using AsyncTask:
AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes. It also has inconsistent behavior on different versions of the platform, swallows exceptions from doInBackground, and does not provide much utility over using Executors directly.
Second one is using Pure Thread
All Android apps use a main thread to handle UI operations. Calling long-running operations from this main thread can lead to freezes and unresponsiveness. For example, if your app makes a network request from the main thread, your app's UI is frozen until it receives the network response. You can create additional background threads to handle long-running operations while the main thread continues to handle UI updates.
official document
and the last method is using Coroutine (just for kotlin)
if you are using kotlin i suggest this one otherwise use AsyncTask
Just try to run your tasks in other Thread and return results by using a callback like interface
first of all I recommend that get familiar with threads in android :
https://developer.android.com/guide/components/processes-and-threads
then , there is some lib to manage threads
AsyncTask , Couroutin , Rxjava . . .
Taking Sina's suggestion to use a Thread, the class now looks like:
public class MainActivity extends AppCompatActivity{
// Irrelevant code (fields, init, other button handlers, etc...)
private void onButtonClick(android.view.View view){
LongRunningThread longRunningThread = new LongRunningThread();
longRunningThread.start();
}
private class LongRunningThread extends Thread{
public void run(){
runOnUiThread(MainActivity.this::showSpinner);
// Logic that takes 5-10 seconds to run
runOnUiThread(MainActivity.this::hideSpinner);
}
}
private void showSpinner(){
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.VISIBLE);
}
private void hideSpinner(){
ProgressBar progressSpinner = (ProgressBar)findViewById(R.id.progressSpinner);
progressSpinner.setVisibility(View.GONE);
}
}
Doing this shows the progress spinner while the long-running logic is running and then hides the progress spinner after the long-running logic has completed. The UI stays responsive throughout and doesn't lock up.
Compared to the original code, this uses Thread instead of ExecutorService. It also runs UI logic via AppCompatActivity.runOnUiThread().
It would seem the answer to doing any long-running tasks alongside UI updates, without locking up the UI, is to create a Thread and call Thread.start(). The Thread should contain the long-running logic as well as the UI logic. The UI logic within that Thread must be run using runOnUiThread().

Application freezes when setting TextView text

I have to update a TextView from another class (not a activity) with the result from a method which can be slow to finish its search. While the method don't finish I thought set the TextView text to something like "loading..." and finally, after method result is ok, set the text to that result. Currently I'm doing something like this:
textView.setText("loading...");
Search s = searcher.search();
textView.setText(s.result);
Firstly, this still freezes the application until result is ok, once didn't not used new Threads. I know that to set content to Android widgets we have to do it inside the uiThread, but I don't know how to do it in my case, once I'm not inside a Activity.
In second place, that approach are not showing the "loading..." text. When I call that code the application just freezes and back with the final text.
Then, how to avoid that freeze/breaking until content is ok?
Do not do heavy operation inside MainThread (UI) in Android. For your case take a look to AsyncTask. It give you a method doInBackground where you should make some background stuff (http request, file i/o) then you will get call onPostExecute, that method will called on UI Thread with the results of doInBackground method. Another example.
I think the main thing to understand is that only UI specific tasks should run on the UI thread. If it is not UI related then it should run on another thread ideally as an AsyncTask.
Performing a search, generally speaking, is very performance heavy as you have pointed out. This will block the UI thread from updating the UI which will lead to unresponsive UIs and users may perceive this a crash or a slow app.
So firstly, to run the updating on the UI Thread.
runOnUiThread(() ->{textView.setText("loading...");});
then perform the search on a different thread
then once the search is finished update the UI using the same method as above

How to know if this thread is a UI Thread

Is there any way on Android to know, if the thread running my code, is the UI Thread or not ? In swing there was SwingUtilities.isEventDispatchThread() to tell me if i am on the UI Thread, or not. Is there any function in the Android SDK that lets me know this ?
Answer borrowed from here: How to check if current thread is not main thread
Looper.myLooper() == Looper.getMainLooper()
Any Android app has only one UI thread, so you could somewhere in the Activity callback like onCreate() check and store its ID and later just compare that thread's ID to the stored one.
mMainThreadId = Thread.currentThread().getId();
Anyway, you can omit checking if you want to do something on the UI thread and have any reference to Activity by using
mActivity.runOnUiThread( new Runnable() {
#Override
public void run() {
...
}
});
which is guaranteed to run on current thread, if it's UI, or queued in UI thread.
Yes, there is a way.
Check the current thread object against main lopper's thread object. Main looper is always in the UI thread.
boolean isOnUiThread = Thread.currentThread() == Looper.getMainLooper().getThread();
Hum actually due to Android architecture, all Activities run in the main thread, ie the UI thread. So when you are coding an activity, everything that is in your Activity is in the UI thread.
That is why in Honeycomb an error have been added when you are making network calls in the main thread : it totally blocks the UI.
So by default you are in fact always working in the UI thread.
Another thing : unless you explicitely ask it to be in another thread, a Service will operate on the same thread as the activities of its application.
So, what to do ?
When you have to do heavy calculation in your activity; one solution is to use an AsyncTask (a class designed to allow you to easily use another thread). The code in onExecute() is run in another thread (but be cautious postExecute runs in your main thread). Another one is to manually start a new thread when AsyncTask is not really adapted.
If you create a service that does costly background tasks, make it run in another thread with the android:process=":my_process" attribute of the manifest. You will need to create an AIDL to communicate with this separated service, but it is not a complicated task.
Many objects, like for example the MediaPlayer, have Async variations of their methods. Try to to always use them.
Put a breakpoint where you want to check and, when it gets hit, check if you can interact with your UI (ie, if the UI is not frozen). If you can't interact with the UI then you are in the UI Thread, otherwise you are in a background thread.

After ASyncTask.execute() do x() from Activity

This is one I'm not sure how to go about.
Basically I have an ASyncTask class thats doing its business as usual in the background. I'd like to do something after its finished. Now before you jump ahead and say "just use onPostExecute()", theres a catch. The method I need run is in the activity and not the Task class.
The way I see it, I have 2 options.
A:
CustomTask task = new CustomTask();
task.execute(passedParams);
//when(task.execute is finished)
{
doX();
}
I hope I can do it this way as Its so simple and lets me check when the task is completed without having to constantly poll it for activity and getStatus() on the activity.
I don't think I'll get this lucky but If anyone has a way of doing it, that'd be great
B:
Pass the activity as a paramater to the ASyncTask. This is messy and I'm not happy about using it but asides from that and the object reference, I don't know if it will work
CustomTask task = new CustomTask();
task.execute(passedParams,MyActivity);
Then in the Tasks onPostExecute, I can just have it call the MyActivity.doX();
C:
A third way would be to make the asynctask a private class in the activity itself but i really would like to keep it separate. Resusability and what not –
Any thoughts on this?
To summarize, Need to doX() after task.execute is finished. Any ideas appreciated.
D:
Ok I know I'm on a roll here. I keep thinking up new solutions. A class method or static method that can be called from any where.
public class ProfileSettings extends Activity
{
public static void doX()
{
//Logic...
}
}
From AsyncTask
MyActivity.doX();
Option B should work and is sometimes a good option, but sometimes I use anonymous classes for this. When you call it from your activity:
CustomTask task = new CustomTask() {
#Override
protected void onPostExecute(Long result) {
super.onPostExecute(result);
MyActivity.this.doX();
}
}.execute();
Option A:
Android API has already provided built-in function for this purpose AsyncTask.get():
CustomTask task = new CustomTask();
task.execute(passedParams);
Result result = task.get(); // <- Block UI thread and waiting for AsyncTask finish.
this.doX(result);
As you can see, this is a bad practice as it blocks UI thread and may cause ANR exception, By doing this, you are actually sacrifice the benefit of AsyncTask, and make it running synchronously with UI thread.
Option B and C:
Both are correct way of doing things, by calling doX() method in onPostExecute() method,
AsyncTask, as its name stated, run a background thread asynchronously with UI thread, and once the background thread is finished, onPostExecute method is called on UI thread. There is no way to tell exactly when onPostExecute method is called (i.e. when doInBackground method is finished) at project build time, as it is determined at app run time, the only thing we know is onPostExecute method is guaranteed to be called on UI thread at some point in the future, In another word, when writing code at project build time, we never know exactly when the doInBackground is finished and code execution jump back to UI thread outside onPostExecute method (Unless you implement some waiting mechanism in code like Option A). So the purpose of onPostExecute method is for processing everything after doInBackground method is finish, this is also why the only argument of onPostExecute method is the result returned from doInBackground method.
The difference between Option B and C is whether to implement AsyncTask as inner class or separate class. This has been aksed and discussed many times in StackOverflow. Most people think it is good to separate them for resusability reason or etc. From my point of view, I don't agree with it. Java Programming Language has its reason provide inner class syntax to suit some special coding situations, when talking about code refactoring from a OOP perspective, think more from problem abstraction level, not simply strip inner class out from Activity class at code level. As you can see in your example, by isolating AsyncTask from Activity, you don't gain any real benefit but rather increase the code complexity (need pass activity context reference between classes) to solve problem.
I think you real question is whether or not we should isolate AsyncTask inner class implementation from Activity. For a better OOP code refactoring (reusability, testability and etc.), checkout my answer in this StackOverflow question to see how to isolate business layer from application UI layer properly.
I was able to implement this feature with an interface:
http://howcanisolve.com/38646/android-java-equivalent-of-ios-block-callbacks
public interface ICallbacks {
public void onResponse(JSONObject response);
public void onError(VolleyError error);
}
Then in your routine code just put a new instance of Callbacks:
public static void getPassagesForFirebaseUser(FirebaseUser user,
Context context, ICallbacks events) {
//here code and call ICallbacks methods
if(result){ events.onResponse(response); }
if(error){ events.onError(err); }
}
ultimately you can call the method with :
getPassagesForFirebaseUser(user, context, new ICallbacks(){
#Override
public void onResponse(JSONObject response){
//Success !!!
}
#Override
public void onError(VolleyError response){
//Error !!!
}
});
Option B is generally safer. But even then, you need to be careful. You need to store the instance of your Activity (not just the class) in the ASyncTask. And if the Activity gets destroyed while the task is running (what if the user presses the Back button?), you need to inform the task of this so the task doesn't try to call a method on a dead Activity.
And if the Activity comes back to life (after a screen rotation, for example) then you need to reattach the new Activity to the running task.
These things are fiddly.

Blocking Dialog from within JNI code

I'm writing an app that's basically a wrapper around a 250K JNI. The JNI (a game engine) has APIs like handle_penUp(int x, int y). Sometimes it needs to query the user from inside handle_penUp() (via callbacks into Java code), so the dialog I use to implement the query must block.
I understand that the main thread of execution can't block. So I've spawned a second thread that makes all the JNI calls that might result in callbacks that would need to block. Inside that second thread, when I need to put up a blocking dialog, I call startActivityForResult() and then acquire() on a semaphore. When onActivityResult() gets called on the main thread it calls release() on the same semaphore.
This works if my query is implemented as a new Activity, but not if I want to showDialog() within the existing Activity. Log messages tell me my thread needs a Looper. I'm adding one -- and will append info on whether it works -- but it feels as if I'm going down the wrong path here. What I need is a recipe for doing blocking dialogs (useful if only because every other platform has them and so ported code will often work that way.)
It sound very close to a problem I had with setting visible/invisible some view from the touch thread.
the problem is that you can't do some operations on the GUI form another thread (which is your case)
what you need to do is to use a Handle in your main thread
I declared it in the Activity
public static final Handler handlerVisibility = new Handler() {
public void handleMessage(Message msg) {
int visibility = msg.getData().getInt("visibility");
view.setVisibility(visibility);
}
};
I chose the option of public static so that I can access in anywhere (because I never have more that one call at a time and that I felt lazy to pass it along to the sub classes).
then what you want to do is send a message to this handler and since the Handler is in the same thread as the gui it works ^^
Message msg = MainActivity.handlerVisibility.obtainMessage();
Bundle b = new Bundle();
b.putInt("visibility", View.VISIBLE);
msg.setData(b);
MainActivity.handlerVisibility.sendMessage(msg);
That should solve your looper error and allow you to send GUI request from one thread to another
hope it helps
Jason
You definitely don't want two UI threads. There should be only one thread that communicates with the Android SDK as far as the control flow and display go (i.e. anything related to drawing, starting activities, displaying dialogs, etc).
Also, keep in mind that you don't want to actually keep your thread running - everything is based on events, so you want your code to respond to something, do something, and then exit as soon as possible.
When you say "block", what exactly do you mean? What needs to be blocked? If you simply need to stop responding to events, why not have a boolean that is set to true while the dialog is visible, and simply ignore all events while it is true?

Categories