I am still confused about callback methods (new to OOP). One definition I found was: "A callback method in java is a method that gets called when an event occurs". What exactly decides when the method will be called? For example, in android, the activity class has an onCreate() callback method that executes whenever an Activity is created, but what code controls this?
Is the doInBackground method of the AsyncTask class also a callback method that executes whenever a foo.execute() is called, where foo is an AsyncTask object?
I see it quite simple like this: lets say you give me your phone number and I'll call you at sunrise. You don't have to worry about how I get up and call your "call-back number", as long as you trust me.
Its the same with a callback method. If the API documents you can supply a method and it will be called when a certain event happens, you don't have to worry about how that's done. Thats the responsibility of the creator of the API.
Related
For example: doInBackground, postExecute, preExecute in android AsyncTask. If I press on a button in my apps, it calls doInBackground method.
How did it happen?
This is a very common design pattern named callback. Check it out: https://en.wikipedia.org/wiki/Callback_(computer_programming)
A callback is often back on the level of the original caller.
In computer programming, a callback, also known as a "call-after" function, is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time. This execution may be immediate as in a synchronous callback, or it might happen at a later time as in an asynchronous callback. In all cases, the intention is to specify a function or subroutine as an entity[clarification needed] that is, depending on the language, more or less similar to a variable (see first-class functions).
Also you can refer the example here: https://github.com/iluwatar/java-design-patterns/tree/master/callback/src/main/java/com/iluwatar/callback
I am in the process of working through the android billing example for an app. The sample app refers to an asynchronous method. I have had a look on the web and I cant seem to find a good definition, please can someone help with an example.
Sample as follows:
// Start setup. This is asynchronous and the specified listener
// will be called once setup completes.
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Is it a method that does not immediately return a result?
If I am not mistaken, you are referring to this method startSetup that accepts a final OnIabSetupFinishedListener and supposedly sets up the billing.
What you seem to be confused about, is this rather syntactically obscure feature of Java called the anonymous inner class.
Let me attempt to answer your question to make it easier:
Is it a method that does not immediately return a result?
Yes, sort of (it of course does not return anything for it is a void method). It, simply speaking, is a method that accepts an instance of the interface OnIabSetupFinishedListener and does some of its job asynchronously as stated in the Javadoc and returns nothing:
This will start up the setup process asynchronously.
Thus, this method is similar to what any other void Java method looks like. The only additional implementation information is that some kind of communication is set up between the listener you pass to this method and some other objects.
But that communication is going to happen at a later point in time, not at the time you call this method, startSetup. Thus, what is important is the call site, i.e. how you are going to call this method in your own app. This, hopefully, happens at the time of setting up your app and you need to get it quickly running and hence this method provides a callback mechanism and returns as soon as possible in a synchronous manner without unnecessary delay. This means your calling thread can make progress and the listener you passed to this method can be utilized later in some other thread when an appropriate event occurs.
The confusion also comes in part because of the way anonymous inner classes are typically coded. Thus, your call site may look like the following:
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
}
});
Here, you are providing an anonymous implementation of the interface OnIabSetupFinishedListener directly at the call site (without actually creating a separate class implementing that interface, using the construct like class MyListener implements OnIabSetupFinishedListener).
Yes. In this context, "asynchronous" means that the method will return immediately and execution will continue with the statement following the method call. Sometime later, the onIabSetupFinished(...) method will be called on the listener. This is called a callback. An important consideration with asynchronous callbacks is what thread they are called in. You'll need to refer to the documentation for this API to find that out.
An asynchronous method is not a typically request/response
You can think of this like a promise or something that will reply without pooling.
In your case you are creating an anonymous listener that will resolve the promise here
public void onIabSetupFinished(IabResult result){
//you will eventually get the response here
}
At runtime, I am using a callback pattern to have generic code run and use the callback when finished to execute code on the GUI. So in my handler I use the runOnUiThread function against the callback.
These are all async http calls. At runtime if I interrupt and use the back button and go to another fragment for example, the system will swap out the fragments and run both callbacks (the new fragment one on the correct callback, and the old callback that should have ran on the old fragment on the new current fragment). This is wrong, the new fragment gets both callbacks but when it was initialized it was assigned to the other fragment...
This makes no sense and you can only observe the behavior by switching fragments at runtime before an async call finishes. I don't see how it's possible, in the code I check if callback is null so it should have been garbage collected and how it runs on the new callback I don't know how it's possible....there's no additional assignment happening to change this. It's almost like it's just looking in memory for the function signature and running it even though when it does it's on the wrong object.
Does anyone have any clue what's going on? I've surpressed it with an ugly piece code, I just don't know how this is possible?
I understand the obvious candidates are if I assigned it again somewhere, but the answer is no. When the fragment is created it creates an object, assigns itself as the callback, and processing begins so when the fragment is destroyed it should be too. But the async task is still executing which is fine, why it does a callback on the new thread on the main gui I guess is because of runOnUiThread, so that function is somehow changing what the callback object points to in memory?
Its your code :-)
There is no magic happening 'behind the scenes' in Android and no references are changed.
Many have problems like yours, and its always because they assume that the Android system is somehow cleaning up when a fragment or activity instance is replaced or removed. It isn't, and therefore the callbacks are still executed, on a obsolete fragment or activity.
runOnUiThread takes a Runnable and runs it when the UI thread have spare time (after invoking lifecycle methods and finished rendering). Its not magic either :-)
So I have a problem and I am wondering how to solve it if it can be solved at all.
I have an external library class called Messenger that defines the method sendMessage(String msg). I also have the following MessengerManager class
public class MessengerManager{
private Messenger messenger;
public MessengerManager(Context context){
messenger = new Messenger(context);
}
public void message(){
String msg = "12435";
messenger.sendMessage(msg);
// Do more stuff
.....
.....
.....
}
}
So the issue is that sendMessage runs asynchronously and starts a new activity. Probably using startActivity() (lets call this Activity A). Hence, the code after sendMessage ("Do more stuff") gets run immediately. However, I need to wait for the newly created activity (Activity A) to return to carry on with the "Do more stuff".
As sendMessage is a method defined in an external library, I cannot change it in any way nor do I have access to its source code.
So, in short, my problem is that sendMessage creates a new thread (using startActivity() probably) and I need to know when this newly created activity ends. However, I have no way of monitoring it since it is defined in an external library. Anyone know how to solve this?
AsyncTask should be what you are looking for.
Let your message() starts an AsyncTask that calls messenger.sendMessage(msg) in doInBackground(). If you care about the result of the AsyncTask, get it in onPostExecute().
http://developer.android.com/reference/android/os/AsyncTask.html
One admittedly ugly way to get around this is to call
Thread.sleep(int milliseconds)
after sendMessage(), and before you continue with the rest of your code. Of course, this will only be helpful if you can fairly accurately estimate how long it will take to get the callback.
The better alternative is as Kaifei is saying. But you won't want the "do more stuff" where it is now. Instead, put it in a new method, and call that method in onPostExecute(). That way, the code will not continue until the AsyncTask has returned.
Edit: Saw your addition about needing the created activity to finish. If that's the case, you're going to somehow need to communicate with that activity (which I can't speak to without seeing all the code). But if you have that, then before "do more stuff", insert
while(!activity.isFinished()) {}
and in that activity, have it set a finished variable to true when it is done (however you define done). So the main thread will run this loop until the activity on the second thread is done, and then the first thread will continue.
Double Edit: Another idea. Let's say that the other activity the user has to complete is some form. In your main activity, after you call sendMessage(), have some popup where the user selects "finished" when they have completed the new activity. Have the program only continue when "finished" has been selected. A bit annoying for the user, but if it's only a single additional tap, that should work.
As you mentioned, sendMessage() runs asynchronously. If it's written properly, it must also have provided a callback interface, whose method will be called when messaging is finished. Move the code in that callback method.
So my problem is as follows, I have an AsyncTask Class that is called from a preference file ie. The intent is called from within an xml file. This AsyncTask Class is continuously running as I am doing a real time FFT of the sound within a room and will only be cancelled if I hit the return button. I cant check for keys being pressed as this Class extends AsyncTask and therefore I cant end the thread properly so that it reaches its onCancelled() state. The only other way I can think about ending this is to make a standby class which is called from the xml file which in turn calls this class and calls the .cancel(true) on the class object.. Any other ideas around this?
Can you post some code?
In your calling method (in which you might be able to check for keys), you can call myASyncTask.cancel() and then in the doInBackground() method of your AsyncTask, you can check for isCancelled() and then break your loop and return to your overridden onCancelled() method of your AsyncTask.
http://developer.android.com/reference/android/os/AsyncTask.html#cancel(boolean)
Does that help?