wait t time before launch an action? - android

I actually had a multiautocompletetextview, where i call host after 3 characters to have a dynamic search list.
But if the user put others characters, my code call host for each of them. So it must be very long.
Could I wait a moment (about 500 ms) before launching the action , in order to look if user do an action or not ? that's possible ?

You could use a separeted thread. When the user entered the text you could create a thread, make it sleep for 500ms and when it will wake up check if the text typed is changed.
EDIT
Create a Handler
private Handler h = new Handler();
Create a runnable that makes your dynamic search
private Runnable myrunnable = new Runnable() {
public void run() {
....
};
Then call your runnable in onTextChanged like
h.postDelayed(myrunnable, 500);
see Handler for more options/informations
Make sure that your threads will access the memory in a consistent way!

Related

Why setText() after sleep doesn't work? Inside android how message queue works?

I know the 2 rules that UI thread shouldn't blocked and udating ui in only UI thread.
So I know roughly why using Thread.sleep() with setText() doesn't work. (Because call Thread.sleep() blocks the UI thread !!)
But...why??
Imagine below code, I clicked a button to start timer to represent number every 50 milli seconds.
public void onTimerClicked(View v){
TextView tv = (TextView) findViewById( .. )
for( int i = 1; i <= 10; i++ ){
Thread.sleep(50) // in milil seconds
tv.setText(String.valueOf(i));
}
}
I already know when I click a button, after I get some freezing time only displays '10' on a text view. But why?? If UI thread encounter tv.setText(..) , it doesn't work for updating UI immediately?? or queueing the task( updating text view UI ) to message queue on main thread?? Then what is the criteria for queueing to message queue instead running the code immediately when it faces.
also, if setting text view with numbers are all queued, then after all sleeping is end. Does UI update all the task very fast?? is it reason that I can only last update ??
I am really curious about how UI thread works for dealing with UI datating internally.. but there are rarely information or explanation about this.
please let me understand !!
Thanks for reading

What is the best thing to use? [duplicate]

This question already has an answer here:
Threading in Android to process long running processes
(1 answer)
Closed 7 years ago.
guys. I want to make a runnable function with Postdelay about 50ms that will be adding Decimal number each time and send a result to activity so I can update this number in the View.I also need it keep running while switching to another activity. As far as I understand the best way is to put it in Sevice in a different thread so it doesn`t slow the UI. I am a beginner so I would like to get some advices from you guys. How should I do this?
Try to use a PostDelay handler for the delay.
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
//DO something
}
}, 1000);
You can just use the View itself with View.postDelayed(yourRunnable, 50).

Android pausing with thread but adding stuff to a text view

I have a linear layout in which I am placing a textview with the id "out". In my code i am getting this textview and calling out.append("Some string here");. What i want to do is have it use a thread.sleep(1000); to wait one second and then do another append. When i just use a for loop and iterate through it ten times it waits ten seconds and then updates the view at the end. How can i make this update the view in between the sleeps?
ps. The main reason for this is because i have another thread running with a bluetooth output stream and i want it to update the textview every time i send a byte to an arduino connected through a bluesmirf module. I can get it to send data but the updating of the screen happens at the end of the for loop. If i put a sleep in this loop it will wait the one second and then output to the arduino no problem. I just want to update it so i can see where things fail as they fail without using the logs.
Maybe you can use a postdelay handler
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//Here is the code you want to run after 1 second
}
}, 1000);
The handler is not blocking, but maybe it can help
Excuse me for my bad english, good luck!

notifyDataSetChanged only refreshes GridView once, despite being called multiple times

I will attempt to summarize my code as follows:
I have a TileAdapter which extends from BaseAdapter to populate a GridView
My TileAdapter contains an array of Tiles that is used to maintain state
My TileUpdate class performs the following operations:
Changes Tile A's colour to green
Calls TileAdapter.notifyDataSetChanged()
Changes Tile B's colour to yellow
Calls TileAdapter.notifyDataSetChanged()
Changes Tile B's colour to red
Calls TileAdapter.notifyDataSetChanged()
I would have expected to see my GridView refresh 3 times, once for each call to notifyDataSetChanged().
However, I only see it refresh after step 6, when and never see Tile B turn yellow.
What is happening here? I presume there is some part of the API I'm not aware of.
Thanks
Update
I still have not been successful in implementing this, even after studying the Handler approaches described below.
So in my UI thread I've created a new GridOperationQueue class which extends from Thread:
public class GridOperationQueue extends Thread {
private Handler handler;
#Override
public void run() {
Looper.prepare();
handler = new Handler();
Looper.loop();
}
public void addTaskToQueue(final GridUpdateTask task)
{
Log.d(this.getClass().toString(), "Current thread is ID " + Thread.currentThread().getId());
handler.post(new Runnable()
{
#Override
public void run() {
Log.d(this.getClass().toString(), " Handler task's current thread is ID " + Thread.currentThread().getId());
task.run();
}
});
}
public void clearQueue(){
handler.removeCallbacksAndMessages(null);
}
}
So my UI thread invokes addTaskToQueue providing a new Task object. The idea is that the task's processing will be performed on a separate thread and after it completes invokes a notifyDataSetChanged() on the UI thread.
However, I've added some logging and it seems that when my tasks run they are still running on the main thread....how would this be? See the following logging:
GridOperationQueue(4393): Current thread is ID 1
GridOperationQueue(4393): Current thread is ID 1
GridOperationQueue(4393): Current thread is ID 1
GridOperationQueue$1(4393): Handler task's current thread is ID 9
TileOperationService$1(4393): Current thread is ID 9
MyActivity(4393): Current thread is ID 9
GridOperationQueue$1(4393): Handler task's current thread is ID 9
TileOperationService$2(4393): Current thread is ID 9
MyActivity(4393): Current thread is ID 9
GridOperationQueue$1(4393): Handler task's current thread is ID 9
TileOperationService$3(4393): Current thread is ID 9
MyActivity(4393): Current thread is ID 9
How come the tasks are still running on the main thread?
I assume you're making all of those changes in your onClick method. The onClick method runs in the UI thread... so, while the code in onClick is running, the UI thread cannot change and tile colors since it's busy. in fact, notifyDataSetChanged simply sets a flag that tells Android to update the changes to the view whenever it can; notifyDataSetChanged does not force an update, but simple tells android one is needed. Thus, you are simply telling android it needs to update the view three times... but, by the time android can actually make the update, which is after your onClick method is done, it can only see the most recent change to the tile color.
How do you get around this? Well, it depends on what you really want to do. for instance, if you want tile color A to change to tile color B when you click the view, and then change to tile color C 500 ms later, do something like this
Handler handler; // instance var
public onCreate(Bundle savedInstanceState) {
...
handler = new Handler();
}
// in your onClick method, wherever it may be (pseudocode)
public void onClick(View v) {
1) set tile color to color B
2) call notifyDataSetChanged
3) schedule a color change in 500 ms:
handler.postDelayed(new Runnable() {
public void run() {
1) set tile color to color C
2) call notifyDataSetChanged
}
}), 500);
You should take a look at Updating the UI from a Timer. The trouble is that when you call notifyDataSetChanged() you only trigger a flag to the GUI. When the adapter gets a repaint it checks if the flag is set and takes action. It does not take any action directly when you call notify.
If you want to update the GUI directly you should learn about the class Handler (see the previous link) so you can post updates to the interface.
Maybe I misunderstood your question, but it seems that you are updating twice the color of Tile B (identical steps 3 and 5 on your question). If that's the case, you will only see the last color (red) and yellow will never be displayed, of course.
Or, you meant "Tile C" on step 5. If this is the case, then the following comments might help:
Even if the UI is changing 3 times, you are probably overriding each color on each call.
1) So your three tiles are 'default' color
2) You update Tile A to green
3) notifyDataSetChanged() is called
(your grid view is updated correctly)
4) You update Tile B to yellow
5) notifyDataSetChanged() is called
(your grid view updates Title B to yellow, but overrides Title A to 'default' color.
6) You update Tile C to red
7) notifyDataSetChanged() is called
(your grid view updates Title C to red, but overrides Title A and B to 'default' color.
That could be the issue.
Also, remember as other guys have mentioned, notifyDataSetChanged() does nothing directly. It only signals the UI to be refreshed when the ideal conditions are met.

"realtime" search using AsyncTask?

I am writing an application that searches a database in "realtime".
i.e. as the user presses letters it updates a search results list.
Since the search can take a while, I need to do the search in background and allow new key presses to re-start a search. So that is a user presses 'a' (and the code starts searching for "a"), then presses 'b' - the code will NOT wait for "a" search to end, then start searching for "ab", but rather STOP the "a" search, and start a new "ab" search.
To do that I decided to do the search in an AsyncTask. Is this a wise decision ?
Now - whenever a keypress is detected, I test to see if I have an AsyncTask running. If I do - I signal it (using a boolean within the AsyncTask) it should stop. Then set a timer to re-test the AsyncTask within 10 mSec, to see if it terminated, and start the new search.
Is this a smart method ? Or is there another approach you would take ?
TIA
First yes, AsyncTask is a good way to do this. The problem I see with your approach is the timer waiting to watch something die. When you invoke the asyncTask hold onto a reference of it. Let it keep state for you so you know if it's out searching or it's has returned. When the user clicks another letter you can tell that asyncTask to cancel. Something like this:
public void onClick() {
if( searchTask != null ) {
searchTask.cancel();
}
searchTask = new SearchTask( MyActivity.this ).execute( textInput.getText() );
}
public class SearchTask extends AsyncTask<String,Integer,List<SearchResult>> {
private boolean canceled = false;
protected onPostExecute( List<SearchResult> results ) {
if( !canceled ) {
activity.handleResults( results );
}
}
public void cancel() {
canceled = true;
}
}
This is safe because onPostExecute() is on the UI thread. And cancel() is only called from the UI thread so there is no thread safety issues, and no need to synchronize. You don't have to watch a thread die. Just let the GC handle cleaning up. Once you drop the reference to the AsyncTask it will just get cleaned up. If your AsyncTask blocks that's ok because it only hangs up the background thread, and when the timeout hits it will resume by calling onPostExecute(). This also keeps your resources to a minimum without using a Timer.
Things to consider about this approach. Sending a new request everytime a new letter is typed can overload your servers because the first few letters are going to produce the largest search results. Either limit the number of results you'll return from the server (say 10-50 results max), or wait until they've entered enough characters to keep results down (say 3). The cons of making the user type more characters is the feedback doesn't kick in until 3 chars. However, the pro is it will dramatically reduce the hits on your server.

Categories

Resources