I have a base abstract class that all my asynctasks extend from. I have built in error handling for network errors where I display a dialog to the user telling them they can retry their request (after all it was a network error...).
I am having a bit of a problem "retrying" my asynctask since once it is executed, you cannot execute it again. How could I go by do that ? Should I use reflection to instantiate the same class and retry?
Has anyone dealt with this problem before?
here seems to be the answer you need:
How to run a retry when download fails in AsyncTask
AsyncTasks are single use and can only be executed once. An exception will be thrown if a second execution is attempted. The solution is just create a new AsyncTask and execute it.
Related
I got an AsyncTask for URL connection. Now I want to have a loading spinner everytime I do the URL connection. I display the loading spinner in onPreExecute() and dismiss it in onPostExecute.
I tested this with an endless while loop in doInBackgroung().
The big problem is the GUI is freezing and the loading spinner is not shown.
In my opinion the reason is URLconnection.execute().get(). But I need the get() because the activity need the result to working with it.
My question is now: What is the best way to do this to achieve my wishes? (By the way it is not important to get a solution with an "AsyncTask solution" because there are maybe better solutions and AsyncTask will be deprecated with SDK version 30)
Thank you very much and stay healthy!
As you said AsyncTask will be deprecated.
So it is better to go for an alternative.
Since you mentioned you are not relying on AsyncTask, I will present to you another approach.
Let me introduce you to coroutines and convince you that they will solve your problem and "get the job done".
When I got to know about coroutines, this video was one of the first example that has demonstrated to me the potential of using coroutines in my app. At that point I was still using 100% Java, probably like you are right now.
The good part is: getting started with Kotlin is really easy! Not only you can call Kotlin functions from Java Code, you can also call Java functions from Kotlin code.
To "do something in background" in Kotlin, all you need to do is to launch a coroutine (on a background thread).
Do you have a ViewModel to fetch your data? If it is an option to transfer this file to kotlin, then starting (and scoping) a coroutine becomes as simple as this.
For fragments or activitities you could use other copes as well. However, using the global scope is usually discouraged.
Executing coroutines is as simple as that:
class MyViewModel: ViewModel() {
fun loadDataInBackgroundAndShowSpinner {
viewModelScope.launch {
// Coroutine that will be canceled when the ViewModel is cleared.
// start your spinning
// do all the heave data work on a background thread
doInBackground()
// end your spinning here
}
}
suspend fun doInBackground(inputURL: String) {
withContext(Dispatchers.IO) {
// Execute all your data fetching here
...
// Assign your data to your viewModel variables, post it to a LiveData object, etc.
}
}
}
You do not need any loops in the main thread or anything. By using withContext on a background thread you can achieve main-safety.
Within a launched coroutine, everything (by default) gets executed in order.
Still you will not block the Main Thread. How did you achieve that?
The key here is that your doInBackground function has the suspend keyword. Therefore your loadDataInBackgroundAndShowSpinner on the main thread will "suspend" your doInBackground function and the main thread is able to do whatever you want (i.e. nothing freezes). Then, once your doInBackground is finished, it will resume execution and you can just dismiss your spinner again on the main thread.
Kotlin coroutines make it so much easier to do something in the background and I really want to encourage you to give it a try! It will definitely solve your problem and I can not think of a more easy way.
Google also tried to make it as easy as possible to get you started when coming from Java.
I am making a chat application.The server will send me an update whenever a friend sends me a message.As a result i need a continuous listener from my android client.I have used asynchronous task and in the post execute method, i have called the asynchronous task again.Thus listening continuously.But this is giving me weird errors.
If you could help me i would be really grateful.If you think i should implement the continuous listener in some other way please do suggest me.Thanks.
Proper method should be like when you get connected to server, you should keep listening in a loop. See my answer here
and modify it as needed.
What about using http://quickblox.com/developers/Android library? I am just curious, if it would not be easier :) .
Otherwise I thought about making while cycle in doInBackground() method, instead of calling asyncTask all over again.
Something like -
While(programExit) {
//your code
}
Hi guys am getting following error am using Websocket and Tomcat8.
java.lang.IllegalStateException: The remote endpoint was in state [TEXT_FULL_WRITING] which is an invalid state for called method
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.checkState(WsRemoteEndpointImplBase.java:1092)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase$StateMachine.textStart(WsRemoteEndpointImplBase.java:1055)
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendString(WsRemoteEndpointImplBase.java:186)
at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendText(WsRemoteEndpointBasic.java:37)
at com.iri.monitor.webSocket.IRIMonitorSocketServlet.broadcastData(IRIMonitorSocketServlet.java:369)
at com.iri.monitor.webSocket.IRIMonitorSocketServlet.access$0(IRIMonitorSocketServlet.java:356)
at com.iri.monitor.webSocket.IRIMonitorSocketServlet$5.run(IRIMonitorSocketServlet.java:279)
You are trying to write to a websocket that is not in a ready state. The websocket is currently in writing mode and you are trying to write another message to that websocket which raises an error. Using an async write or as not such good practice a sleep can prevent this from happening. This error is also normally raised when a websocket program is not thread safe.
Neither async or sleep can help.
The key problem is the send-method can not be called concurrently.
So it's just about concurrency, you can use locks or some other thing. Here is how I handle it.
In fact, I write a actor to wrap the socketSession. It will produce an event when the send-method is called. Each actor will be registered in an Looper which contains a work thread and an event queue. Meanwhile the work thread keeps sending message.
So, I will use the sync-send method inside, the actor model will make sure about the concurrency.
The key problem now is about the number of Looper. You know, you can't make neither too much or too few threads. But you can still estimate a number by your business cases, and keep adjusting it.
it is actually not a concurrency issue, you will have the same error in a single-threaded environment. It is about asynchronous calls that must not overlap.
You should use session.get**Basic**Remote().sendText instead of session.get**Async**Remote().sendText() to avoid this problem. Should not be an issue as long as the amount of data you are writing stays reasonable small.
Actually a basic Java question which I did not come along when I was learning this programming language.
For best understanding my question I will provide a simple sample:
block of code {
-new AsynTask..
-some code which I want to execute after AsyncTask finishes executing..
}
I know I can put the second line of code in postExcecute in AsyncTask object. But is it possible for program flow to continue after AsyncTask is finished executing?
You don't want to do this. This totally destroys the purpose of using an AsyncTask- it will halt the original thread until the task is done, preventing it from doing other things. If you wanted to do that, you'd be better off without the task. Instead, you should put the code you want to execute after the task is done in the onPostExecute method of the AsyncTask.
So I have this Java piece of code where I need to do some work on a bunch of items. I decided to parallelize this to get some extra boost and I though to use a ThreadPoolExecutor. The problem is that the work I need to do can throw an exception...
Now I would like to shutdown the entire job to stop as soon as an error is encountered and report it back so I can handle it. Looking online, I found that the normal way this should be done is via ExecutorCompletionService and analyzing the Future results. However, this won't let me shut everything down when the first error comes by, as there is no way to loop over based on which task finishes first...
So I did something that I thought was rather hacky and I'm curious if there is a better way to handle this. What I did was:
1) Have each Runnable that I will execute have a field for the Throwable that it might execute.
2) Override the TPE's "afterExecute" method and check if any checked exception got thrown (which gets recorded in the Runnable) or any unchecked one gets thrown (which should be reported in the second parameter of this method). If any did, then I issue a shutdownNow() on the TPE.
Again, this seems a bit hacky and I am wondering if there is something I am missing. Thanks in advance!
Look at ExecutorService.invokeAny:
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do. Upon normal or exceptional return, tasks that have not completed are cancelled. The results of this method are undefined if the given collection is modified while this operation is in progress.
It looks it does the exact same thing you are trying to do... if I understood your problem correctly.
However for cancel to do anything, you have to make your Callable tasks interrupt aware. But that applies no matter how you try to cancel your tasks.
EDIT:
This is not what you need; I misread the javadoc. Here's another solution: you could put all your Future's in a list and then have a semi-busy while loop where you check periodically on each futureList.get(i).get(100, TimeUnits.MILLISECONDS) and you can catch an exception and act accordingly. However, this no more "elegant" than your solution. It seems that afterExecute was made to do what you want anyway.