How to update the UI smoothly? - android

So from what I've read, Android's AsyncTask is a great way to asynchronously load information from the Internet. However, I don't want to block up the UI and prevent the user from interacting with it.
A basic description of my problem.
Currently, I am using websockets in order to send/receive data from a web server. On events like a user entering the room, a song being added or removed from a playlist, a song being upvoted or downvoted, or one song ending and another one beginning, the UI must be updated in order to indicate changes. But ideally, these changes will be occurring very frequently, which means that constantly blocking the UI in order to refresh it would be cumbersome and annoying.
How would I update my UI without interrupting the user in their activities? Would AsyncTask suffice?

The asyncTask does not block the UI. It runs on a separate thread to send / receive the data from the web, and then returns the results. When you receive the results back, you can update the UI as you choose.
Your UI will not be stopped while the asyncTask is performing its background work. You can try it out by by building one in your activity and simply sleeping for some amount of time (let's say five seconds) in the doInBackground method. You will see that your UI is still functional during that five seconds.
Edit: You can do just about anything with the results you get back and it won't interrupt your UI either. If that's not the case, you'll probably want to look at optimizing what you are doing with your in memory objects. Anything not stored in memory should probably be retrieved or written to disk, database, or internet endpoint with an AsyncTask. As the commenter points out above, this is not the only way to use other threads, but it's easy and will probably work if you're making a reasonable web request and expect users to have a decent connection. You will just want to make sure you have timeouts and exceptions covered so that your app doesn't crash if the task takes longer than expected.
public class LoadCommentList extends AsyncTask<Integer, Integer, List<Comment>> {
private String commentSubject;
public LoadCommentList(commentSubject){
this.commentSubject = commentSubject;
}
// Do the long-running work in here
protected List<Comment> doInBackground(Integer... params) {
// the data producer is a class I have to handle web calls
DataProducer dp = DataProducer.getInstance();
// here, the getComments method makes the http call to get comments
List<Comment> comments = dp.getComments(commentSubject);
return comments;
}
// This is called each time you call publishProgress()
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
// This is called when doInBackground() is finished
protected void onPostExecute(List<Comment> comments) {
// calls a method in the activity to update the ui
updateUI(comments);
}
}
There are cleaner examples actually using the Integer... params for example, but this is just something I had handy as an example.

I don't know where you read that but asyn task are worst way to make web service call this days. You should use Retrofit for service call, it is 8 Times faster and handle UI update smoothly.
Read more about this here :-
http://googleweblight.com/?lite_url=http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit&ei=qR4bQU5c&lc=en-IN&s=1&m=260&host=www.google.co.in&ts=1465531978&sig=APY536z0v15lfX3G6KY4nls4wf1kzttJdA

Related

Android: Put all code on a background thread

Lets say i'm developing a mobile application. As we know, by default, most of the code is going to run on the UI thread.
I want my application to run as smoothly as possible for my users, so i make sure that I am using async/await in all possible places.
On slower android devices, I am still having issues with Logcat telling me that I am skipping frames. So my next thought is to make sure that everything that can be done on a background thread, is put on a background thread. So besides work that has to be done on the UI thread, i put all of my code inside tasks on background threads.
My question is, Can I theoretically put too much code onto background threads, where I am actually making my application slower due to having to move between background threads and the UI thread too much?
You can do that quickly and can still controllable using Observable.
Observable.just("")
.observeOn(AndroidSchedulers.mainThread())
.flatMap { //do UI here }
.observeOn(Schedulers.io())
.doOnNext{ //do Async here }
.subscribe()
You need to use for background execution. Use AsyncTask.
public class SyncDatabase extends AsyncTask<List<ProductModel>, Void, Integer> {
#Override
protected Integer doInBackground(List<ProductModel>[] lists) {
return YOUR_INT;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(Integer row) {
super.onPostExecute(row);
// This is mainThread
//you can do what ever you want example: textView.settext(row+"");
}
}
Now you call from main thread
new SyncDatabase().execute(YOUR_GIVEN_LIST);
Yes you can put lots of job in background thread. You can use android threadpool system for group by group thread execution
You can do this if you are confident enough to handle all the thread communication efficiently by yourself. I would suggest using react approach. There are different react libraries available now for Android.
In reactive systems, A full job is broken into several parts. Different workers called Actors perform a different part of the full job and when finishes forward the job to next worker. Channels are used to send and receive messages between workers.

Show a message when doing synchronous server request

I am working on an app where i do some calls in synchronized manner using the
class HttpUtil extends AsyncTask<Void,Void,String>
{...}
HttpUtil httpUtil = new HttpUtil();
httpUtil.execute((Void[]) null).get();
This will call to a AsyncTask method.
Issue:
The spinning wheel is not shown in the UI since we do a UI blocked request. Even if I add a toast then the toast is displayed after the request is completed.
If I make asynchronous calls then I get the spinning wheel as the UI was not blocked
Expected:
I need to show a spinning wheel for the blocked request(done adding get() method) also.
Do not use get() on a network operation. Just don't. Your app will freeze, and either get killed by the system, or the user will be frustrated that your app blocks the entire UI of the system. It's absolutely unacceptable, and there is no reason why a well-designed app should need to resort to that.
You turn on your indeterminate progress in the AsyncTask's onPreExecute(), and turn it off in onPostExecute(). These two methods are always run on the UI threat. Please refer to the documentation for AsyncTask.
Further, you won't need to pass Void[] null to the execute() call -- just pass nothing, which will result in an empty array of Void.
If any other operations or UI updates depend on the result of the request, then do those updates in onPostExecute. If you want to create modality to essentially "halt" the UI while the request is running, then display a dialog box, but please provide a cancel option.

Mono Android: terminate thread in onPause() state

I am running into a strange problem...
My application is meant to do some webservice calls on a separate thread. Once the webservice call is finished, it would navigate user to a different activity.
In the case when user press the home button or exit current activity it should terminate the webservice if the webservice call thread is still running. Hence I put a thread termination method in the OnPause state.
Here is the method block that is running inside the thread:
private Thread _webserviceThread;
void WebserviceCallThread(){
WebRestult result= WebserviceCall();
if(!result.containsError()){
RunOnUIThread(delegate{
transitionToActivityXYZ();
});
}
}
void RunThreadAction(){
_webserviceThread = new Thread(new ThreadStart(WebserviceCallThread));
_webserviceThread.Start();
}
protected override void OnPause(){
if(_webserviceThread != null && _webserviceThread.IsAlive){
_webserviceThread.Abort();
}
}
After the webservice call is done and begin the transition to another page, It gets to the OnPause state. However, in some strange cases, it would think that the thread is not finished in the OnPause state, even though the activity transition is the last line of the method.
Has anyone ran into this problem before? If so, how did you solve this problem?
Thanks!
I always use AsyncTask for this kind of thing. Not only does it abstract away the explicit thread handling and provide hooks to do everything you want here; it's also a nice way to represent a unit of work that can be used from other activities.
There's a simple example in this post part way down, but it doesn't use the generic parameters which are quite handy.
Why not use Task Parallel Library,
It is standard .NET, and with AsyncTask, it is only recommended for tasks that take less than few seconds. see the Documentation
AsyncTasks should ideally be used for short operations (a few seconds
at the most.) If you need to keep threads running for long periods of
time, it is highly recommended you use the various APIs provided by
the java.util.concurrent
Below is an example for how to use Task Parallel Library, taken from here
private void loginWithTaskLibrary()
{
_progressDialog.Show();
Task.Factory
.StartNew(() =>
_loginService.Login("greg")
)
.ContinueWith(task =>
RunOnUiThread(() =>
onSuccessfulLogin()
)
);
}

Implementing a cyclic executive in android?

I am writing an android app and I need to be able to do certain things periodically/continuously. I am coming from a C/C++ embedded firmware background and this new-fangled way of doing things is going to take some getting used to. It seems that there is no such thing as a "main loop" in Android, that everything is event-driven... I also understand that by default all code you write operates on the GUI thread, and I should probably make a new thread to execute the equivalent of a "main loop"...
So far what I have is an implementation of the AsyncTask class who's "doInBackground" method contains an infinite loop (my main loop), I create an instance of this class and run it immediately when my app starts. The problem I am having is in the interaction between this thread and the user interface... when something occurs in my main loop thread and I want to update the GUI understand that I must call "publishProgress", which is executed on the GUI thread. There are a few problems with this, primarily that many things I have tried to do in this "onProgressUpdate" method do not work, or do not occur in a predictable amount of time.
My question, is there a better way to accomplish what I am trying to do? In general, what do most people do when they have code that they want to run periodically and/or continuously while their application is running, code that must interact with the user interface in a timely manner (by timely I mean with zero delay).
Thank you.
public class MainLoopThread extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
while(true)
{
//Do stuff
//Update GUI
publishProgress();
}
}
protected void onProgressUpdate(Void...voids)
{
//Update GUI
}
}
It is unclear what you are trying to do, however just let me say using AsyncTask in this way may have negative consequences.
AsyncTask internally uses a thread pool pattern for running the stuff from doInBackground(). On Android OS before 1.6 and starting from 3.0 the pool size is just 1, meaning no parallel computations for a bunch of AsyncTasks. More details on this here.
So, this may result that only this current AsyncTask is running, while others even if started will have to wait untill the current one is done.
Depending on your needs for things to be done periodically Android exposes:
AlarmManager
Handler - it allows to post a runnable on UI thread with a delay or periodically
Timer + Activity.runOnUiThread(Runnable action) inside of TimerTask
UPDATE: basing on your comments it looks like you need a Service, that starts a thread that periodically sends broadcasts with the data for UI. Then your UI (Activity) registers broadcast receivers to catch those broadcasts, extract the data and use for UI updates.
So your saying that onProgessUpdate() isn't working? That seems weird because it should.
Another option that you have is just to make a Thread that loops.
The trick is that if you want to update the UI thread you will have to make a call to view.post() and give it a runnable that will actually perform the update. The idea here is that you must schedule an update on the UI thread, you can't just take it and say NOW!

Stop HTTP requests in async tasks on changing activity

I am downloading multiple images in an activity to populate a list view, all in seperate async tasks. In this activity the user can press a button to go to another page which doesn't require the images.
The issue I run into is that even on going to the next activity the async tasks are still running and the httpclient isn't released for the requests that need to be made in this next activity.
I tried using asynctask.cancel for all the tasks running, but that throws an interruptedIOException.
Is there any other graceful way of stopping the requests that are being made to free up the client?
Ideally, what you want to do in these kinds of situations is to wrap your HTTP requests in a loop that can be cancelled. Using this question as an example (full implementation there):
#Override
protected Void doInBackground(Void... params) {
while (running) {
// loop your HTTP requests here
}
return null;
}
When you trigger the onCancelled() method (by calling cancel), your doInBackground method will terminate as soon as the current HTTP request is complete (and not before).
This is likely to be the most graceful solution you're going to get using AsyncTask. Also, you might have to catch the interrupted exception somewhere in your AsyncTask class, but this should be enough to get you going.

Categories

Resources