Android: pass function reference to AsyncTask - java

I'm new to android and very used to web developing. in javascript when you want to perform an asynchronous task you pass a function as an argument (a callback):
http.get('www.example.com' , function(response){
//some code to handle response
});
I was wondering if we can do the same with android's AsyncTask , pass a function reference to the onPostExecute() method , and it will run it.
any suggestions ?

Yes the concept of callbacks also very much exists in Java. In Java you define a callback like this:
public interface TaskListener {
public void onFinished(String result);
}
One would often nest these kind of listener definitions inside the AsyncTask like this:
public class ExampleTask extends AsyncTask<Void, Void, String> {
public interface TaskListener {
public void onFinished(String result);
}
...
}
And a complete implementation of the callback in the AsyncTask would look like this:
public class ExampleTask extends AsyncTask<Void, Void, String> {
public interface TaskListener {
public void onFinished(String result);
}
// This is the reference to the associated listener
private final TaskListener taskListener;
public ExampleTask(TaskListener listener) {
// The listener reference is passed in through the constructor
this.taskListener = listener;
}
#Override
protected String doInBackground(Void... params) {
return doSomething();
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// In onPostExecute we check if the listener is valid
if(this.taskListener != null) {
// And if it is we call the callback function on it.
this.taskListener.onFinished(result);
}
}
}
onPostExecute() is called as soon as the background task finishes. You can use the whole thing like this:
ExampleTask task = new ExampleTask(new ExampleTask.TaskListener() {
#Override
public void onFinished(String result) {
// Do Something after the task has finished
}
});
task.execute();
Or you can define the TaskListener completely separately like this:
ExampleTask.TaskListener listener = new ExampleTask.TaskListener() {
#Override
public void onFinished(String result) {
// Do Something after the task has finished
}
};
ExampleTask task = new ExampleTask(listener);
task.execute();
Or you can subclass TaskListener like this:
public class ExampleTaskListener implements TaskListener {
#Override
public void onFinished(String result) {
}
}
And then use it like this:
ExampleTask task = new ExampleTask(new ExampleTaskListener());
task.execute();
You can of course just override the onPostExecute() method of the AsyncTask, but that is not recommended and in most cases actually pretty bad practice. For example you could do this:
ExampleTask task = new ExampleTask() {
#Override
public void onPostExecute(String result) {
super.onPostExecute(result);
// Your code goes here
}
};
This will work just as well as the implementation above with a separate listener interface, but there are a few problems with this:
First and foremost you can actually break the ExampleTask all together. It all comes down to the super.onPostExecute() call above. If you as a developer override onPostExecute() like above and forget to include the super call or simply delete it for whatever reason that the original onPostExecute() method in the ExampleTask will not be called anymore. For example the whole listener implementation with the TaskListener would suddenly not work anymore since the call to the callback is implemented in onPostExecute(). You can also break the TaskListener in many other ways by unknowingly or unwittingly influencing the state of the ExampleTask so it won't work anymore.
If you look at what's actually happening when you override a method like this than it becomes much more clear what's going on. By overriding onPostExecute() you are creating a new subclass of ExampleTask. It would be the exact same thing as doing this:
public class AnotherExampleTask extends ExampleTask {
#Override
public void onPostExecute(String result) {
super.onPostExecute(result);
// Your code goes here
}
}
All this is just hidden behind a language feature called anonymous classes. Suddenly overriding a method like this doesn't seem so clean and quick anymore does it?
To summarise:
Overriding a method like this actually creates a new subclass. You are not just adding a callback, you are modifying how this class works and can unknowingly break oh so many things.
Debugging errors like this can be much more than just a pain in the a**. Because suddenly ExampleTask could throw Exceptions or simply not work anymore for no apparent reason, because you never actually modified its code.
Each class has to provide listener implementations at places where it is appropriate and intended. Sure you can just add them later on by overriding onPostExecute() but that is always very dangerous. Even #flup with his 13k reputation has forgotten to include the super.onPostExecute() call in his answer, imagine what some other not as experienced developer might do!
A little abstraction never hurt anybody. Writing specific listeners might be slightly more code, but it is a much better solution. The code will be cleaner, more readable and a lot more maintainable. Using shortcuts like overriding onPostExecute() essentially sacrifices code quality for a little bit convenience. That is never a good idea an will just cause problems in the long run.

In Java, functions are less of a first class citizen than in JavaScript. The AsyncTask provides the callback as a method in the class, which you should override.
See Make an HTTP request with android for a subclass of AsyncTask with an implementation of the doInBackground which makes a web request.
If you want to do multiple HTTP requests with different callbacks, you can override RequestTask and implement onPostExecute with the different callback implementations.
You can use an anonymous class to simulate the closure a JavaScript callback commonly uses:
new RequestTask(){
#Override
public void onPostExecute(String result) {
// Implementation has read only access to
// final variables in calling scope.
}
}.execute("http://stackoverflow.com");
As Xaver shows, you can also create a full-blown interface for the listener. This seems only useful to me if you wish to implement a couple default onPostExecute functions and pick one of these default implementations for a particular call.

in Kotlin
Firstly, create class AsyncTaskHelper as below.
class AsyncTaskHelper() : AsyncTask<Callable<Void>, Void, Boolean>() {
var taskListener: AsyncListener? = null
override fun doInBackground(vararg params: Callable<Void>?): Boolean {
params.forEach {
it?.call()
}
return true
}
override fun onPreExecute() {
super.onPreExecute()
}
override fun onPostExecute(result: Boolean?) {
super.onPostExecute(result)
taskListener?.onFinished(result as Any)
}
}
interface AsyncListener {
fun onFinished(obj: Any)
}
the code below you can use when you want to use async task.
AsyncTaskHelper().let {
it.execute(Callable<Void> {
//this area is the process do you want to do it in background
// dosomething()
}
}
null
})
it.taskListener = object : AsyncListener{
override fun onFinished(obj: Any) {
// this area is for the process will want do after finish dosomething() from Callable<Void> callback
}
}
From the code above. if you want to separate your process to several task. you can do as this code below.
AsyncTaskHelper().let {
it.execute(Callable<Void> {
// task 1 do in background
null
},Callable<Void>{
// task 2 do in background
null
},Callable<Void>{
// task 3 do in background
null
})
it.taskListener = object : AsyncListener {
override fun onFinished(obj: Any) {
// when task1,task2,task3 has been finished . it will do in this area
}
}
}

I also want to contribute to Sup.la's Kotlin solution by making it a little more generic in case you're only interested in .execute()ing a function asnychronously and .get()ting a result from an AsyncTask.
I split up the explanation in order to make it better understandable.
If you only want to copy paste, just skip to Step2 :)
Note: Keep in mind that AsyncTask is deprecated now. However, I think it'll stay around for while due to compatibility and stuff.
Step 1
This is how the generic class can look like:
import android.os.AsyncTask
#Suppress("DEPRECATION") // As mentioned, AsyncTask is deprecated now
class GenericAsyncTask() : AsyncTask<Callable<Any>, Void, Any?>() {
override fun doInBackground(vararg params: Callable<Any>): Any? {
// params receives vararg, meaning its an Array.
// In this example we only want pass one function to easen up the example (-> [0]).
return params[0]?.call()
}
}
As can be seen, the AsyncTask now takes any function passed to it (Callable<Any>), whereby Any and null can be the result of the function. Thus, here nobody cares about the types the AsyncTask has to handle or return or how the passed function looks like.
You can now use it like this:
// In this example lets assume we have a method which returns a list of Strings
var res: List<String>? = GenericAsyncTask().let {
it.execute(
Callable<Any> { your_random_function() }
).get() as? List<String>?
}
As you can see, we handle the Any dilemma just by casting it. This works since all Types are deriving from Any except null. To handle the latter, we're doing a safe cast using as?. Thus, also null as return-type is handled.
Step2
However, ultimatively we can even make this more generic:
// The same example result as shown above
// The casting will be inferred directly from your_random_function() return-type
val res: List<String>? = GenericAsyncTask().async(::your_random_function)
// For the sake of completeness, this is valid as well
val res: List<String>? = GenericAsyncTask().async<List<String>?> { your_random_function() }
class GenericAsyncTask() : AsyncTask<Callable<Any>, Void, Any?>() {
// This function takes any method you provide and even infers the result-type, thus, spares you the casting
public fun<T> async(method: () -> T): T? {
return this.let {
it.execute(Callable<Any> { method() }).get() as? T?
}
}
override fun doInBackground(vararg params: Callable<Any>): Any? { ... }
}

Related

Best Approach for Readable Ordered AsyncTask Code

I'm going round in circles trying different techniques but every time hitting a different snag.
Ideally I want my code to look something like;
public class MyActivity extends AppCompatActivity {
SomeMethod();
new SomeAsyncTask().execute();
SomeOtherMethod();
new SomeOtherAsyncTask().execute();
}
But I need each method to be executed in order (and to wait for the previous to complete). Let's imagine the first AsyncTask authenticates and stores an authentication token in a static somewhere- this is then needed for the calls which follow.
My AsyncTasks have to be Async as they are communicating with an API.
I know I could use the onPostExecute() methods of the AsyncTasks but I don't like the mess this creates (having to jump around the code).
I know I could also create an interface and pass a class in to my AsyncTask but this doesn't help a great deal either (code still jumps around).
I thought I had come up with the perfect solution, calling SomeAsyncTask.execute().get() to wait until the task completes before continuing with the next line of code BUT I've hit a few issues with that today too.
Are there any other techniques I might be able to use to achieve clean code with a mix of foreground and background thread activity?
EDIT At the moment I am considering whether I can make all of my method non-async but then call them from an async- more like;
public class MyActivity extends AppCompatActivity {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground( final Void ... params ) {
SomeMethod();
SomeMethod2();
SomeOtherMethod();
SomeOtherMethod2();
return null;
}
#Override
protected void onPostExecute( final Void result ) {
// any ui stuff
}
}.execute();
}
EDIT2 Current favoured solution is;
Define a "PostExecute" interface in my AsyncTask;
public class GetMerchantDataAsync extends AsyncTask<Void, Void, Void> {
private Context mContext;
private PostExecute mDelegate;
public interface PostExecute {
void Callback();
}
public GetMerchantDataAsync(Context context, PostExecute delegate) {
mContext = context;
mDelegate = delegate;
}
#Override
protected Void doInBackground(Void... params) {
}
#Override
protected void onPostExecute(Void v){
mDelegate.Callback();
}
}
Then define an instance of the interface and pass it on the constructor;
public class StartActivity extends Activity {
private final Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new GetMerchantDataAsync(context, getMerchantDataPostExecute).execute();
}
private GetMerchantDataAsync.PostExecute getMerchantDataPostExecute = new GetMerchantDataAsync.PostExecute() {
#Override
public void Callback() {
DoSomethingElse();
}
};
}
It's a little bit messy (not a single block of code) but it almost reads as a single block and hopefully with sensible/consistent naming will be easily readable.
There are many ways to skin this cat and a few nice async await libraries you can use, similar to Promise.
Or you can also simply do onPostExecute call backs inline if that fits your needs and call the next step onPostExecute, assuming life cycle is still valid.
However, if you want some nice clean code, you should consider Kotlin and Coroutines.
Example with Timeout, cancellation and error handling:
Notice the withTimeout and the withContext calls. Those allow you to await on the contents within before moving on. Also as an added bonus, the method here is a suspendable coroutine which means the caller can wait on it as well. You resume the caller with c.resume(returnValueType).
If you find this too complicated, then I would stick with your onPostExecute, but what most developers forget on AsyncTasks are.
AsyncTasks should be canceled if you exit the Activity typically
AsyncTasks can complete out of order if you are allowing threadpool
management
Object locks must be wrapped to ensure concurrent
modification of variables does not become a problem.
Callbacks should handle errors and not just the positive route
Timeouts have to be managed outside of the Async task adding much more bloat.
So you see, simply doing a myAsyncTask.execute{onPostExecute(value){//dostuff}}
may look like simple fast code, it is definitely prone to errors if you don't handle all the niche cases that can occur.
The Coroutines have provided nice wrappers around all of this in easy to read brackets.
private suspend fun updateConfigurationWithChanges() : Boolean = suspendCoroutine { c ->
A35Log.v(mClassTag, "updateConfigurationWithChanges")
setIsActionInProgress(true)
mSaveOrUpdateJob = launch(UI) {
try{
withTimeout(TIMEOUT_FOR_DB_INTERACTION_MS){
showProgressDialog(mClassTag, "Saving", false)
mSelectedConfiguration!!.setLastSavedDateStr(DateTimeHelper.getNowTimeStamp())
val updatedRecordCount = withContext(DefaultDispatcher){ SSDBHelper.updateConfiguration(mSelectedConfiguration!!) }
if(updatedRecordCount > 0){
showFancyToast("Successfully updated", true, FancyToast.SUCCESS)
c.resume(true)
}else{
showFancyToast("Error while updating, please try again or press back", true, FancyToast.SUCCESS)
c.resume(false)
}
}
}catch(ex: JobCancellationException){
showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
c.resume(false)
}catch (ex: TimeoutCancellationException) {
showFancyToast("Timed out updating, please try again or press back", true, FancyToast.ERROR, "Timed out updating database: ${ex.message}")
c.resume(false)
}catch(ex: Exception){
showFancyToast("Error updating database, please try again or press back", true, FancyToast.ERROR, "Error updating database: ${ex.message}")
c.resume(false)
}
}
}
Of course it is still good practice to cancel if the user leaves your screen if it doesn't hurt anything.
override fun onPause() {
super.onPause()
if(mSaveOrUpdateJob != null && mSaveOrUpdateJob!!.isActive) {
A35Log.v(mClassTag, "canceling saveOrUpdate job")
mSaveOrUpdateJob?.cancel()
}
}
But at the end of the day, do what's best for your situation, if managing the asyncTask and onPostExecute works for your needs and you have all your i's dotted and your t's crossed you should be fine going that route as well.
Also just for completeness if you are wondering how to call and await this above method it would look like this.
fun myButtonClick(){
launch(UI) {
if(mIsNewConfiguration){
//save first if new
if(withContext(DefaultDispatcher){ isNewOrUnchangedName() }) {
if (withContext(DefaultDispatcher) { saveNewConfigurationToDatabase() }) {
refreshCurrentNamesList()
launchConnectAndSendToDeviceFlow()
}
}
}else {
//update first if changes made
if(withContext(DefaultDispatcher){ isNewOrUnchangedName() }) {
if(DeviceAndConfigurationHelper.hasConfigurationModelChanged(mOriginalCopyConfiguration!!, mSelectedConfiguration!!)){
if(withContext(DefaultDispatcher) { updateConfigurationWithChanges() }){
refreshCurrentNamesList()
launchConnectAndSendToDeviceFlow()
}
}else{
launchConnectAndSendToDeviceFlow()
}
}
}
}
}
Happy Coding.
I can think of two approaches, depending on your constraints you can pick any of them, one using custom async tasks:
Create a custom AsyncTask which will be inherited by all your async tasks (or it can be done inline too):
public abstract class BaseAsyncTask<T, U, V> extends AsyncTask<T, U, V> {
public interface Callback<X> {
void onComplete(X param);
}
private Callback mainCallback;
public void execute(Callback<V> callback, T... params) {
mainCallback = callback;
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
}
#Override
protected void onPostExecute(V v) {
super.onPostExecute(v);
if (mainCallback != null) {
mainCallback.onComplete(v);
}
}
}
This can be used like this for your case:
public static class TestThinghy {
BaseAsyncTask<String, String, String> task = new BaseAsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... strings) {
return null;
}
};
void firstFunOnMainThread() {
//....do whatever...///
}
void runEverything() {
firstFunOnMainThread();
new BaseAsyncTask<String, String, String>() {
#Override
protected String doInBackground(String... strings) {
return "testing thinghy";
}
}.execute(new Callback<String>() {
#Override
public void onComplete(String param) {
secondRunOnMainThread();
//you can start new async here, or better start it from a different methond
}
}, "the other string param");
}
void secondRunOnMainThread() {
///...whatever here
}
}
The other approach is using RxJava, it's a powerful approach that gives you a ton of ways to chain tasks like this and decide how to run them, for this approach I would let you to do some research.

How to stop repeating myself in Java

I use a method for more than one time in JavaScript by using callback method because JavaScript is an async language.
Example:
function missionOne () {
sumCalculation(1, 2, function (result) {
console.log(result) // writes 3
})
}
function sumCalculation (param1, param2, callback) {
let result = param1 + param2
// The things that take long time can be done here
callback(result)
}
I wonder if there is any way to stop myself in Java?
Edit: I remove several sentences that make more complex the question.
I may be reading too much into your question, but it seems that you're looking into how to handle asynchronous code in Android. There are a couple of native options (not considering any library). I'll focus on two, but keep in mind there are other options.
AsyncTasks
From the documentation
AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
Before writing one, you need to know which type of parameters it will receive, the type of progress it will publish during computation and what is its return type. These types are define via the AsyncTask generic Parameters AsyncTask<Params,Progress,Result>. If you don't need them any of them, set them to Void
Here's the basic gist of using an AsyncTask to compute the sum of two ints:
public void sumCalculation (int param1, int param2, Callback callback) {
new AsyncTask<Integer, Void, Integer>() {
#Override
public Integer doInBackground(Integer... params) {
int result = 0;
for (Integer param : params) {
result += param;
}
return result;
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
callback.onDone(integer);
}
}.execute(param1, param2);
}
doInBackground, as the name says, will execute a certain piece of code in a background thread. Please note that every AsyncTask will run on a ThreadPool of size 1, so they actually get in the way of other AsyncTasks.
onPostExecute brings the result back to the main thread, so you can update any UI componente. If you try to update the UI from a background thread, an exception will be thrown.
The down side of this particular example is the creation of a new AsyncTask every time that function is called.
Also you should use AsyncTask only if the task won't run for a very long time, couple of seconds at most.
Thread and Handler
Another option suggested on the documentation is using a thread and a handler to communicate between the main thread and a background thread. Although this provides greater flexibility, it also requires more responsibility as you will be responsible for managing the communication yourself, picking the right time to kill your threads and how to recover when something goes bad.
As a rule of thumb, you should only go this way if you really need the extra flexibility.
The overall idea is to create your own Handler and override its handleMessage method.
public class MyHandler {
#Override
public void handleMessage(Message inputMessage) {
int messageType = inputMessage.what;
Object extraData = inputMessage.obj;
...
}
}
public class MyTask extends Thread {
public static public int COMPUTATION_DONE = 0;
private MyHandler handler;
public MyTask(MyHandler handler) {
this.handler = handler;
}
#Override
public void run() {
//do your computation
Message message = handler.obtainMessage(COMPUTATION_DONE, your_result);
handler.sendMessage(message);
}
}
As you can see, this requiring parsing inputMessage.what and deciding what to do with it. Additionally, you need to cast inputMessage.obj to the right type and so on.
These are just two examples, but depending on what you're trying to do, you might need to dig deeper into Services or take a look at some reactive approach, such as RxJava2. However I encourage you to start with the basic before diving into something way more complicated.
Yes it is easy in Java. To take your example above you can write it in Java like this:
public static void main(String[] args) {
System.out.println(sumCalc(1,2));
}
private int sumCalc(int first, int second) {
return first + second;
}

Best way to get result from an AsyncTask to the caller class

I have implemented a way of getting the result from onPostExecute back to my main activity. I wanted to know if this is the right thing I did, is there any more chance of improving it, and if it's not the best way, what is the best way?
This is what I have done:
public class MainClass implements AsyncResponse {
private MyAsyncTask asyncTask;
public MainClass() {
asyncTask = new MyAsyncTask();
asyncTask.asyncResponse = this;
}
public void startTask( {
asyncTask.execute("string");
}
#Override
public void processDone(String res) {
// got response in MainClass from onPostExecute
}
private class MyAsyncTask extends AsyncTask<String, String, String> {
protected AsyncResponse asyncResponse = null;
#Override
protected String doInBackground(String... urls) {
return "some processed string";
}
#Override
protected void onPostExecute(String res) {
this.asyncResponse.processDone(res);
}
}
}
Here's the AsyncResponse interface:
public interface AsyncResponse {
void processDone(String res);
}
I want to know in terms of processing speed that on an average android mobile device, would this be a good approach and if not, how do I improve it to make it a good approach?
Thanks.
I always done this way and never had any issues. I would say it is the best way.
in one Line without any callback
String s= new MyAsyncTask().execute().get();
You added an unnecessary interface - and perhaps it makes your code less usable.
First, if you create the AsyncTask as a class within your Activity there is no need for the interface. You can simply do this:
#Override
protected void onPostExecute(String res) {
processDone(res);
}
The AsyncTask will execute onPostExecute on the UI thread and you can call the Activity method without the interface.
Second, if you create AsyncTask outside the Activity class (for example, in its own java file) then you can use this method, except it is not a good idea because it will hold a reference to the Activity on another thread - it's a memory leak risk.
To avoid that, your interface should be implemented in a separate class, like AsyncTaskResponse.java that is passed to the AsyncTask class.
Last, AsyncTask provides the response in the form of a String if that is sufficient. You should look at the docs on AsyncTask:
https://developer.android.com/reference/android/os/AsyncTask.html
You are wrapping the AsyncTask inside another POJO class; doing this doesn't hurt, but provides little benefit.
Consider that when the task is completed, you will want a callback notification somewhere. Your MainClass will get a callback in processDone(), but something will need to be listening to MainClass to get that notification.
Here is a pattern I always use with my AsyncTask subclasses:
public class GetDataRemoteTask extends AsyncTask<String, Void, Data> {
private static final String TAG = "GetDataRemoteTask ";
private WeakReference<GetDataResultListener> mListenerRef;
private Exception mExc;
#Override
protected Data doInBackground(String... params) {
Data result = null;
try {
result = mService.getData(params[0], params[1], params[2]);
} catch (Exception e) {
Log.e(TAG, "Error occurred getting data", e);
mExc = e;
}
return result;
}
#Override
protected void onPostExecute(Data result) {
if (mListenerRef != null) {
GetDataResultListener listener = mListenerRef.get();
if (listener != null) {
if (mExc == null) {
listener.dataReceived(result);
} else {
listener.dataException(mExc);
}
}
}
}
public void setGetDataResultListener(GetDataResultListener listener) {
if (listener == null) {
this.mListenerRef = null;
} else {
this.mListenerRef = new WeakReference<GetDataResultListener >(listener);
}
}
public static interface GetDataResultListener {
public void dataReceived(Data data);
public void dataException(Exception exc);
}
}
So to start off, here I have an interface, like you do, for connecting to the AsyncTask. But I don't wrap my AsyncTask with an implementation, I expect that I will have an Activity or a Fragment that will implement this interface. (That's why I use a WeakReference; if the Activity finishes, my AsyncTask won't keep holding on to the Activity. But that also means I can't use an anonymous class listener unless the client holds the reference for it.)
My client code will look like this:
GetDataRemoteTask task = new GetDataRemoteTask();
task.setListener(this);
task.execute(param1, param2, param3);
I also have a way to find out if there was an exception that occurred in the background task. Any background exceptions should always be reported to the client, which can decide how best to deal with the exception - for example pop up a dialog for the user, so they know the request failed.
I think that a big drawback of AsyncTask is that it doesn't have more structure around handling exceptions that occur in the background thread.
My task holds a reference to the exception, but I have also used Pair<Data, Exception> as a type parameter for return result so I don't need the exception property.
Using this pattern has helped me avoid some typical problems that occur when coding AsyncTask subclasses.

Activity collides with AsyncTask? How to implement AsyncTask into GUI?

I am sorry for my bad english skills. I'm new to programming/stackoverflow and try to create a little android quiz app. This app has to connect to a php server and login/getquestion...
The simplest example is the login. The user has to type in his data and then i have to connect.
To provide that the Gui doesnt freeze i have to use asynchronous tasks.
Here the activity's code:
public void login(final String username, final String password) {
final Activity a = this;
FutureTask t = new FutureTask(new Callable() {
public Object call() {
Connection.GetInstance(a).login(username,password);
afterLoginTry(username,password);
return null;
}
});
t.run();
}
This calls a method in another class, which calls another FutureTask which calls an AsyncTask. At the end there is always an public synchronized method such as afterlogintry(). This works but it's a bit slow and i think dirty code.
My main problem is that i don't know how to give results back through different layers of classes and especially to the activity without using hotfixes all the time.
Is there any good explanation or tutorial, which describes how to design such a construct?
Thx for help
The way you can pass AsyncTask results back to other classes, is by declaring callbacks for the task, that will then report the result to a listener. Here is how it works.
First, you must declare an interface in your AsyncTask which contains a method that will send out the result of the task. So in my example task below, my result is a String. The String gets passed to onPostExecute() when the task finishes its work. I then call my callback method on a registered listener, and pass that return value on to whoever is listening for it. You register a listener by passing in an instance of your callbacks from whichever class is creating the task.
public class MyTask extends AsyncTask<String, Void, String> {
MyTaskCallback listener;
public MyTask(MyTaskCallback listener) {
this.listener = listener;
}
protected String doInBackground(String... params) {
String input = params[0];
//do work
input += "did some work on this String";
return input;
}
//When the thread finishes its work, this gets
//called on the main UI thread
protected void onPostExecute(String result) {
listener.onResultReceived(result);
}
public interface MyTaskCallback {
void onResultReceived(String result);
}
}
So next we need to register a listener for these callbacks, so when the result comes in from the task, it will get reported directly to our class. So let's say we have a simple Activity. The way we register the callbacks is to use the implements keyword on our class declaration, and then to actually implement the callback method in the class itself. We then create our task, and we pass in this which is our Activity that implements the callbacks. A simple example Activity that does this looks like this:
public class TaskActivity extends AppCompatActivity implements MyTask.MyTaskCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
//we pass in "this" because our Activity itself
//implements the callbacks below.
MyTask myTask = new MyTask(this);
myTask.execute();
}
//Here we implement our callback method, so the task
//can send its results straight through here
public void onResultReceived(String theResult) {
Log.d("TASK RESULT", "Here is our result String: "+theResult);
}
}
Now, our task has our Activity connected to it, through the callbacks we passed into it. So now when our task gets a result, we can send it directly to our listener, which is our Activity, and the result will come right through to our implemented onResultReceived method.
Callbacks are a great way to pass information around between classes while also keeping everything very separated. Hope this helps!

Observable which does not pass anything in onNext()

I would need an Observable, for example to provide a system clock, which does not need to pass anything in onNext(). I couldn't find a signature that would allow me to do that.
Sure, I could use any object and then pass null, but that doesn't make much sense. So my question is if there is a better way to do that.
Observable.create(new Observable.OnSubscribe<Anyobject>() { // use any object in the signature
#Override public void call(Subscriber<? super Anyobject> subscriber) {
subscriber.onNext(null); // then pass null
subscriber.onCompleted();
}
})
You don't need to call onNext if your Observable doesn't emit anything.
You could use Void in your signature and do something like
Observable<Void> o = Observable.create(new Observable.OnSubscribe<Void>() {
#Override
public void call(Subscriber<? super Void> subscriber) {
// Do the work and call onCompleted when you done,
// no need to call onNext if you have nothing to emit
subscriber.onCompleted();
}
});
o.subscribe(new OnCompletedObserver<Void>() {
#Override
public void onCompleted() {
System.out.println("onCompleted");
}
#Override
public void onError(Throwable e) {
System.out.println("onError " + e.getMessage());
}
});
You can define an OnCompletedObserver to simplify your Observer callback so that you don't have to override the onNext since you don't need it.
public abstract class OnCompletedObserver<T> implements Observer<T> {
#Override
public void onNext(T o) {
}
}
If I've understood what you're asking then this should do the trick.
If you need something to be passed to onNext() before onCompleted() is called:
Observable.<Void>just(null)
If you only need onCompleted() to be called:
Observable.empty()
RxJava 2 Wiki:
RxJava 2.x no longer accepts null values and the following will yield
NullPointerException immediately or as a signal to downstream.
...
This means that Observable<Void> can no longer emit any values but
only terminate normally or with an exception. API designers may
instead choose to define Observable<Object> with no guarantee on what
Object will be (which should be irrelevant anyway)
It means that you can't use Void and do Observable.just(null).
Use Object or some other simple type instead:
Observable.just(new Object());
Starting with RxJava 2, the propper way to do this is to use a Completable
From the docs:
Represents a deferred computation without any value but only
indication for completion or exception. The class follows a similar
event pattern as Reactive-Streams: onSubscribe (onError|onComplete)?
One of the light solutions is to use Observable<Boolean>
And then onNext(Boolean.TRUE) which you then just ignore.
But probably you shouldn't use Observable in that case.
Consider using Completable instead
I don't know this will helps you or not.
The code written in RxSwift.
// Create an observable and emit somethings
let myObservable = Observable<Void>.create{ observer in
observer.on(.next(Void()))
return Disposables.create()
}
// Observer subscribe changes
myObservable.subscribe(onNext: {
_ in
print("Hello")
}).disposed(by: disposeBag)
Or use the Variable object
// Create a Variable object that contanins nothing
var myValueWatcher:Variable<Void> = Variable<Void>(Void())
// Observer subscribe changes
myValueWatcher.asObservable().skip(1).subscribe(onNext: {
_ in
print("Changes!")
}).disposed(by: disposeBag)
// The emit code
myValueWatcher.value = Void()

Categories