Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Threads and UI in Android

Reply
Thread Tools

Threads and UI in Android

 
 
Dirk Bruere at NeoPax
Guest
Posts: n/a
 
      04-03-2011
Part of the problem I have been having with adding data to a listview
stems from the threads I have running. Specifically, I have a thread
that constantly checks for messages coming over the Wifi/LAN. When it
finds one it loads the datagram, then calls a static method from a class
BlinkAPI which calls other BlinkAPI methods which loads the data into
arrays.

So far so good - no problems.
However, if the Android ListView in the UI is to be updated with this
data there is a problem. I cannot go in and do stuff to the ListView
from BlinkAPI or I get a message about "called from wrong thread".

Given that loading up Listviews, adapters etc should be done from the
same UI thread, how best to put a "break" between my LAN thread and the
UI thread?

--
Dirk

http://www.neopax.com/technomage/ - My new book - Magick and Technology
 
Reply With Quote
 
 
 
 
Dirk Bruere at NeoPax
Guest
Posts: n/a
 
      04-03-2011
On 03/04/2011 19:16, Dirk Bruere at NeoPax wrote:
> Part of the problem I have been having with adding data to a listview
> stems from the threads I have running. Specifically, I have a thread
> that constantly checks for messages coming over the Wifi/LAN. When it
> finds one it loads the datagram, then calls a static method from a class
> BlinkAPI which calls other BlinkAPI methods which loads the data into
> arrays.
>
> So far so good - no problems.
> However, if the Android ListView in the UI is to be updated with this
> data there is a problem. I cannot go in and do stuff to the ListView
> from BlinkAPI or I get a message about "called from wrong thread".
>
> Given that loading up Listviews, adapters etc should be done from the
> same UI thread, how best to put a "break" between my LAN thread and the
> UI thread?
>


It would seem the answer is in here somewhere
http://developer.android.com/resourc...threading.html

--
Dirk

http://www.neopax.com/technomage/ - My new book - Magick and Technology
 
Reply With Quote
 
 
 
 
Lawrence D'Oliveiro
Guest
Posts: n/a
 
      04-03-2011
In message <(E-Mail Removed)>, Dirk Bruere at NeoPax wrote:

> It would seem the answer is in here somewhere
> http://developer.android.com/resourc...threading.html


Seems like AsyncTask is the way to go: it automatically divides up execution
between a background thread and the UI thread, and takes care of all the
synchronization between the two for you.

How much more painless can you get?
 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      04-04-2011
On 4/3/2011 12:27 PM, Dirk Bruere at NeoPax wrote:

>> So far so good - no problems.
>> However, if the Android ListView in the UI is to be updated with this
>> data there is a problem. I cannot go in and do stuff to the ListView
>> from BlinkAPI or I get a message about "called from wrong thread".



This seems analogus to Java Swing & EDT. Use the Activity.runOnUiThread
method to send processing to the UI thread, so you won't get this message.

Given:

some other thread
|
|
V
public void someMethod( Params.... ) {
// do set up

// do this on UI thread

// do clean up
}

Transform this to:

some other thread
|
|
V
public void someMethod( Params.... ) {
// do set up

Activity.runOnUiThread( new Runnable() {
public void run() {
// do this on UI thread
}
} );

// do clean up
}

To run the center bit of code on the UI thread. Note that you are
executing code asynchronously and the "clean up" will likely happen
before the UI thread bit. Something to be aware of.

 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      04-04-2011
On 4/3/2011 3:16 PM, Lawrence D'Oliveiro wrote:
> In message<(E-Mail Removed)>, Dirk Bruere at NeoPax wrote:
>
>> It would seem the answer is in here somewhere
>> http://developer.android.com/resourc...threading.html

>
> Seems like AsyncTask is the way to go: it automatically divides up execution
> between a background thread and the UI thread, and takes care of all the
> synchronization between the two for you.
>
> How much more painless can you get?




Given that the OP want's to "constantly [check] for messages" I think
the way he's doing it now is fine. runOnUiThread() does the
synchronization that he needs, and it seems cleaner than trying to wrap
his deamon in an AsyncTask object and constantly call publishProgress()
whenever he gets a packet.

Modern threading is getting sophisticated, and one sophisticated thing
to do is to limit the number of threads so as to not overwhelm the OS.
Limited thread pools are used for this purpose. I don't know how
AsynchTask is implemented, but if it uses a thread pool, you could
easily starve your own app of threads for AsynchTask by permanently
capturing too many AsynchTask threads, which is what the OP's task would do.

"Long running" tasks relative to the UI response time go in AsynchTask.
"Really long running" tasks, or permanent tasks like the OP's little
network daemon, go in their own private thread. Seems safest that way.

 
Reply With Quote
 
John B. Matthews
Guest
Posts: n/a
 
      04-04-2011
In article <inb4mo$2br$(E-Mail Removed)>, markspace <-@.> wrote:

> On 4/3/2011 3:16 PM, Lawrence D'Oliveiro wrote:
> > In message<(E-Mail Removed)>, Dirk Bruere at NeoPax wrote:
> >
> >> It would seem the answer is in here somewhere
> >> http://developer.android.com/resourc...threading.html

> >
> > Seems like AsyncTask is the way to go: it automatically divides up execution
> > between a background thread and the UI thread, and takes care of all the
> > synchronization between the two for you.
> >
> > How much more painless can you get?

>
> Given that the OP want's to "constantly [check] for messages" I think
> the way he's doing it now is fine. runOnUiThread() does the
> synchronization that he needs, and it seems cleaner than trying to
> wrap his deamon in an AsyncTask object and constantly call
> publishProgress() whenever he gets a packet.
>
> Modern threading is getting sophisticated, and one sophisticated
> thing to do is to limit the number of threads so as to not overwhelm
> the OS. Limited thread pools are used for this purpose. I don't know
> how AsynchTask is implemented, but if it uses a thread pool, you
> could easily starve your own app of threads for AsynchTask by
> permanently capturing too many AsynchTask threads, which is what the
> OP's task would do.
>
> "Long running" tasks relative to the UI response time go in
> AsynchTask. "Really long running" tasks, or permanent tasks like the
> OP's little network daemon, go in their own private thread. Seems
> safest that way.


I have no practical experience on android, but I was struck by the
similarity between AsyncTask and SwingWorker:

<http://developer.android.com/reference/android/os/AsyncTask.html>
<http://download.oracle.com/javase/6/...wingWorker.htm
l>

It appears to be of more recent vintage, and it supports either a
SERIAL_EXECUTOR or THREAD_POOL_EXECUTOR, with certain caveats for the
latter.

--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>
 
Reply With Quote
 
Dirk Bruere at NeoPax
Guest
Posts: n/a
 
      04-04-2011
On 04/04/2011 01:51, markspace wrote:
> On 4/3/2011 3:16 PM, Lawrence D'Oliveiro wrote:
>> In message<(E-Mail Removed)>, Dirk Bruere at NeoPax wrote:
>>
>>> It would seem the answer is in here somewhere
>>> http://developer.android.com/resourc...threading.html

>>
>> Seems like AsyncTask is the way to go: it automatically divides up
>> execution
>> between a background thread and the UI thread, and takes care of all the
>> synchronization between the two for you.
>>
>> How much more painless can you get?

>
>
>
> Given that the OP want's to "constantly [check] for messages" I think
> the way he's doing it now is fine. runOnUiThread() does the
> synchronization that he needs, and it seems cleaner than trying to wrap
> his deamon in an AsyncTask object and constantly call publishProgress()
> whenever he gets a packet.
>
> Modern threading is getting sophisticated, and one sophisticated thing
> to do is to limit the number of threads so as to not overwhelm the OS.
> Limited thread pools are used for this purpose. I don't know how
> AsynchTask is implemented, but if it uses a thread pool, you could
> easily starve your own app of threads for AsynchTask by permanently
> capturing too many AsynchTask threads, which is what the OP's task would
> do.
>
> "Long running" tasks relative to the UI response time go in AsynchTask.
> "Really long running" tasks, or permanent tasks like the OP's little
> network daemon, go in their own private thread. Seems safest that way.
>


Currently I have this:

public class BlinkDataThread extends Thread
{
int length = Constants.PACKET_LENGTH;
byte[] receiveBuffer = new byte[length];
DatagramSocket socket;
DatagramPacket packet;

public void run()
{
try
{
DatagramSocket ds = new DatagramSocket(Constants.LOCAL_PORT);
DatagramPacket incoming = new DatagramPacket(receiveBuffer,
receiveBuffer.length);
incoming.setLength(length);
String packetStr=new String(receiveBuffer, "UTF-8");

while(true) //Run this as an endless loop
{
ds.setReceiveBufferSize(receiveBuffer.length);
ds.receive(incoming);
packetStr = new String(receiveBuffer, 0,
incoming.getLength(), "UTF-8");
if (packetStr != null) BlinkAPI.updateIncomingData(packetStr);
}
} catch (IOException e1) {}
}

}

Where linkAPI.updateIncomingData(packetStr); is the offending bit since
it triggers updates on the UI thread.

That would be where I use runOnUiThread()?

--
Dirk

http://www.neopax.com/technomage/ - My new book - Magick and Technology
 
Reply With Quote
 
Lawrence D'Oliveiro
Guest
Posts: n/a
 
      04-04-2011
In message <(E-Mail Removed)>, Dirk Bruere at NeoPax wrote:

> Where linkAPI.updateIncomingData(packetStr); is the offending bit since
> it triggers updates on the UI thread.
>
> That would be where I use runOnUiThread()?


OK, if it’s running in an endless loop, I guess that’s not suitable for an
AsyncTask.

I believe the recommended mechanism for posting actions back to the UI
thread is via a Handler
<http://developer.android.com/reference/android/os/Handler.html>: create
this from the UI thread, pass it to the background thread, and the latter
can use the post method to send back a Runnable to be executed.

By the way, note that faceless background threads can be killed at any time.
 
Reply With Quote
 
Dirk Bruere at NeoPax
Guest
Posts: n/a
 
      04-04-2011
On 04/04/2011 06:23, Dirk Bruere at NeoPax wrote:
> On 04/04/2011 01:51, markspace wrote:
>> On 4/3/2011 3:16 PM, Lawrence D'Oliveiro wrote:
>>> In message<(E-Mail Removed)>, Dirk Bruere at NeoPax
>>> wrote:
>>>
>>>> It would seem the answer is in here somewhere
>>>> http://developer.android.com/resourc...threading.html
>>>
>>> Seems like AsyncTask is the way to go: it automatically divides up
>>> execution
>>> between a background thread and the UI thread, and takes care of all the
>>> synchronization between the two for you.
>>>
>>> How much more painless can you get?

>>
>>
>>
>> Given that the OP want's to "constantly [check] for messages" I think
>> the way he's doing it now is fine. runOnUiThread() does the
>> synchronization that he needs, and it seems cleaner than trying to wrap
>> his deamon in an AsyncTask object and constantly call publishProgress()
>> whenever he gets a packet.
>>
>> Modern threading is getting sophisticated, and one sophisticated thing
>> to do is to limit the number of threads so as to not overwhelm the OS.
>> Limited thread pools are used for this purpose. I don't know how
>> AsynchTask is implemented, but if it uses a thread pool, you could
>> easily starve your own app of threads for AsynchTask by permanently
>> capturing too many AsynchTask threads, which is what the OP's task would
>> do.
>>
>> "Long running" tasks relative to the UI response time go in AsynchTask.
>> "Really long running" tasks, or permanent tasks like the OP's little
>> network daemon, go in their own private thread. Seems safest that way.
>>

>
> Currently I have this:
>
> public class BlinkDataThread extends Thread
> {
> int length = Constants.PACKET_LENGTH;
> byte[] receiveBuffer = new byte[length];
> DatagramSocket socket;
> DatagramPacket packet;
>
> public void run()
> {
> try
> {
> DatagramSocket ds = new DatagramSocket(Constants.LOCAL_PORT);
> DatagramPacket incoming = new DatagramPacket(receiveBuffer,
> receiveBuffer.length);
> incoming.setLength(length);
> String packetStr=new String(receiveBuffer, "UTF-8");
>
> while(true) //Run this as an endless loop
> {
> ds.setReceiveBufferSize(receiveBuffer.length);
> ds.receive(incoming);
> packetStr = new String(receiveBuffer, 0, incoming.getLength(), "UTF-8");
> if (packetStr != null) BlinkAPI.updateIncomingData(packetStr);
> }
> } catch (IOException e1) {}
> }
>
> }
>
> Where linkAPI.updateIncomingData(packetStr); is the offending bit since
> it triggers updates on the UI thread.
>
> That would be where I use runOnUiThread()?
>


Or not.
That BlinkAPI.updateIncomingData(packetStr) eventually gets to call this
from the Data class

public static void setRadioTitleAdapterListView()
{
radioLV.setAdapter(radioTitleAdapter);
radioTitleAdapter.notifyDataSetChanged();
radioLV.setVisibility(VISIBLE);
}
It is really this I need to execute in the UI thread.
Is there some way of wrapping that method (amongst several of the same
type) as a message to the UI thread telling it to execute
Data.setRadioTitleAdapterListView() from there?

[I can send the packet received in the BlinkDataThread but that rather
defeats the idea since all the heavy duty processing occurs after it is
picked up.]

--
Dirk

http://www.neopax.com/technomage/ - My new book - Magick and Technology
 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      04-04-2011
On 4/4/2011 11:18 AM, Dirk Bruere at NeoPax wrote:

> Or not.
> That BlinkAPI.updateIncomingData(packetStr) eventually gets to call this
> from the Data class
>
> public static void setRadioTitleAdapterListView()
> {



I don't like the idea that you're suggesting here. Hard baking this
method so it always runs on the UI thread sounds bad. You want to keep
methods flexible so they can be used in a variety of contexts. Too much
specialized behavior results in classes that require too many support
classes or a specialized environment to function at all.

Better to do it where you had it at first. You're already processing
the packet and making a string. It seems fine to allow your Blink
routine to process the resulting string on the UI thread. You don't
have to be manic about removing every last cycle from the UI thread,
just keep long tasks (like IO, or sorting or searching) away from it.

Also, in the code you posted, you set up packetStr once outside of the
loop, then never use that value, so I'm moving packetStr inside the loop
and removing the unused assignment.

And I think you mean !packetStr.equals( "" ), not packetStr != null. It
isn't possible to get null from a constructor.


public void run()
{
try
{
DatagramSocket ds = new DatagramSocket(Constants.LOCAL_PORT);
DatagramPacket incoming = new DatagramPacket(
receiveBuffer, receiveBuffer.length);
incoming.setLength(length);
// not used String packetStr=new String(receiveBuffer, "UTF-8");

while(true) //Run this as an endless loop
{
ds.setReceiveBufferSize(receiveBuffer.length);
ds.receive(incoming);
final String packetStr = new String(receiveBuffer, 0,
incoming.getLength(), "UTF-8");
if( !packetStr.equals( "" ) ) {
Activity.runOnUiThread( new Runnable() {
public void run() {
BlinkAPI.updateIncomingData(packetStr);
}
} );
}
} catch (IOException e1) {
// you really must log errors if you find them
// honestly, you'll be happy you did.
}
}
}

At least we're doing things now that look like actual Java programming.



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
C++ And TDD/ C++ programming on Android/ String Calculator Kata inC++/ C++and OpenGL on Android with the NDK/c++ Convert Integers to Roman Numerals sterta bole C++ 0 08-27-2012 09:09 PM
[ANN] Android Debug Bridge (ADB) Scripting Language For Android(SL4A) convenience library Stef Mientki Python 0 11-27-2011 04:46 PM
Android, Android, Android Lawrence D'Oliveiro NZ Computing 2 05-21-2011 05:06 AM
[new to threads] threads with UI and loop Une bvue Ruby 0 06-14-2006 10:22 AM



Advertisments