I need to pass a huge amount of data (raw bytes) between threads - listener thread and another thread that deals with the data manipulation. Whats the best and fastest way to do that?
As others have pointed out it really depends on the task you have. I would suggest using a Message. For example if one of your threads is a producer of said byte[] data and the other is the consumer you may have something of the sorts:
public class ProducerThread extends Thread{
byte[] data;
public void run(){
while (isRunning){
Looper.prepare();
data = someMethodToGetYourByteData();
Message dataToSend = Message.obtain();
Bundle bundle = new Bundle();
bundle.putByteArray("data", data);
dataToSend.setData(bundle);
if (ConsumerThread.mHandler!=null){
ConsumerThread.mHandler.sendMessage(dataToSend);
}
Looper.loop();
}
}
and your consumer thread:
public class ConsumerThread extends Thread{
public static Handler mHandler;
byte[] data;
public void run(){
while (running){
Looper.prepare();
mHandler = new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mHandler.obtainMessage();
data = msg.getData().getFloatArray("data");
doSomethingWithData(data);
};
}
Looper.loop();
}
Keep in mind though that this may not be the best pattern to use, as many elsewhere on SO point out that it is not the best idea to extend a Thread, but it generally depends on the use case.
Let us say the two threads are T1 and T2. Let us say we implement them using separate AsyncTasks A1 and A2. Now execute A2 from the onPostExecuteMethod of A1 passing necessary parameters to the execute method. This works fine because onPostExecute method runs in foreground and with respect to ui thread so that the A2 is executed only when A! has finished executing.
Since your talking about large amounts of data. The best way is to wrap your byte[] in an Object. You can do your own custom class but most people use ByteBuffer because it already has a good manipulation API and can be used with the Java NIO sub-system.
Related
When using a background thread to do work, typically you'd update the UI through a Handler.
One way to do this was defining a handler at the class level as outlined in this answer, and this answer
final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
//update UI or call class methods here
}
};
However, this construct would result in the following warning
Handler class should be static otherwise memory leaks might occur
Another way to do this was to use a static inner class as outlined in this answer, and this answer
static class MyHandler extends Handler {
private final WeakReference<Type> myWeakReference;
MyHandler(Type reference) {
myWeakReference = new WeakReference<Type>(reference);
}
#Override
public void handleMessage(Message msg)
{
//Update UI or call class methods here using weak reference
}
}
However, this form of constructor has been Deprecated according to the Android docs.
public Handler ()
This constructor is deprecated. Implicitly choosing a Looper during
Handler construction can lead to bugs where operations are silently
lost (if the Handler is not expecting new tasks and quits), crashes
(if a handler is sometimes created on a thread without a Looper
active), or race conditions, where the thread a handler is associated
with is not what the author anticipated. Instead, use an Executor or
specify the Looper explicitly, using Looper#getMainLooper, {link
android.view.View#getHandler}, or similar. If the implicit thread
local behavior is required for compatibility, use new
Handler(Looper.myLooper()) to make it clear to readers.
How should updating the UI from a Handler be done currently, and should a Handler still be used for this purpose.
As you stated the docs, it says to use Looper.getMainLooper(), just change your code to:
MyHandler(Type reference) {
super(Looper.getMainLooper());
myWeakReference = new WeakReference<Type>(reference);
}
to update the UI from the main/UI thread.
I am reviewing/cleaning up some Android code. The code did some "asynchronous" network and data operations using this pattern:
new Thread() { public void run() { { ... runOnUiThread( { .. } ) }
A lot. With all the ugly consequences (no error checks, Sleeps, boolean finish variables...).
Till now, I ended up using (few) AsyncTasks and (more) Loaders as replacements.
Now I have stumbled upon a couple of "fire-and-forget" network communications: the code (currently, a Thread, as always) calls a web service posting some data.
I do not need to know if the data was received, and I do not need to know if there was any error.
Which is the best way of doing this? A Runnable or AsyncTask (static nested class, so I do not "leak" a reference to "this" activity?)
Or is there something better (more "lightweight" and cleaner?)
If you don't need to know when task execution is finished then you definitely don't need AsyncTask at all. Therefore the most lightweight solution is just a Thread. You can use Executor which will create threads for you. To get rid of nested classes you could predefine tasks. Sample:
Predefined task:
public static class TaskA implements Runnable{
private int someParam;
public TaskA(int someParam) {
this.someParam = someParam;
}
#Override
public void run() {
//
}
}
Static Executor
public static class FireAndForgetExecutor{
private static Executor executor = Executors.newFixedThreadPool(5);
public static void exec(Runnable command){
executor.execute(command);
}
}
And usage:
FireAndForgetExecutor.exec(new TaskA(10));
PS don't forget that a Thread is connected to the GC root! So if you pass heavy object like an activity or a bitmap into the task it could lead to memory leak.
I did a lot of research, but I didn't get through it, so that i don't know how to realize my App. The App consists of 2+ Activities, that contain content, that should be updated by a service in the background. So I dont know how to do the connection, some say i should do ipc, but others say thats too much of work, as long as service and activites run within the same process. I concerned to easily create methods like ActivityOne.RefreshData(Data data) and call those within the service, but i did not manage to get it work until now. I hope you have some suggestions to me and sorry for my bad english!
cheers
If you only need to provide data/updates to your own activities then IPC is most certainly not needed.
To achieve this, I would reverse the orientation you seem to be describing and rather than have the service calling methods on the activity, have it pushing messages to a Handler provided to it by the Activity when/if it starts.
See:
http://developer.android.com/reference/android/os/Handler.html
http://mobileorchard.com/android-app-developmentthreading-part-1-handlers/
Note that if what you need to send from the service to activites is always the same type of object, you can simplify your implementation of handleMessage() by using the Message.obj field to hold your type and not bother with Bundles or parcelling. As in:
Handler impl in activity where NotificationModel is the type that the service always sends:
private Handler mNotificationListener = new Handler(){
#Override
public void handleMessage(Message msg) {
handleIncomingNotification((NotificationModel)msg.obj);
}
};
The service side of posting msgs to this handler looks like:
public class NotificationRouter {
private Application mContext;
private SparseArray<Handler> mListeners = new SparseArray<Handler>();
public NotificationRouter (Application app){
this.mContext = app;
}
public void registerListener(Handler handler){
mListeners.put(handler.hashCode(), handler);
}
public void unRegisterListener(Handler handler){
mListeners.remove(handler.hashCode());
}
public void post(NotificationModel notice){
Message m = new Message();
m.obj = notice;
for (int i = 0; i < mListeners.size(); i++){
Handler h = mListeners.valueAt(i);
h.sendMessage(m);
}
}
}
For example, if I have a thread doing expensive stuff, and from that thread I want to fire runOnUiThread in the Main (activity) class. Obviously I shouldn't make an instance of my activity class (Main). So if I try
Main.runOnUiThread(mRunnable);
from my thread it gives me an error saying it's not a static method, and therefor it can't be accessed in my way. Now my understanding would be that the activity class is nearly almost accessed in a static way.
How would I do this?
(Btw: I'm doing this because I was getting CalledFromWrongThreadException, Only the original thread that created a view hierarchy can touch it's views)
Raunak has the right idea. I'll just add that you can also specify an integer in the method sendEmptyMessage as an identifier to the handler. This will allow you to create one handler that can handle all of your UI updates, e.g.
public static final int EXAMPLE = 0;
public static final int ANOTHER_EXAMPLE = 1;
private final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
switch( msg.what ){
case EXAMPLE:
//Perform action
break;
case ANOTHER_EXAMPLE;
//Perform action
break;
}
}
}
//Call to submit handler requesting the first action be called
handler.sendEmptyMessage(EXAMPLE);
Hope this helps!
You should use the Handler class. The handler class runs on the UI thread. When you finish work in your thread, call handler.sendEmptyMessage(), from where you can make the changes to your ui.
private final Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
// make changes to ui
}
}
Your question doesn't really provide enough details, but from the sound of things, you're in a private inner class (Runnable?) in your activity (Main). If that is the case, you can either write:
Main.this.runOnUiThread(mRunnable);
or
runOnUiThread(mRunnable); //will see that there is no runOnUiThread in the current class and begin looking "upwards"
Also, you may want to look at AsyncTask, specifically at the onPostExecute, onPreExecute and onProgressUpdate callbacks, which run on the UI thread.
first create a runnable outside onCreate. Like this:
private Runnable myRunnable = new Runnable() {
#Override
public void run() {
//work to be done
}
};
and then call the runnable using:
runOnUiThread(myRunnable);
all of the above answers are not very correct.
1)if you want a piece of code to run on UI thread from any thread code base. you can do:
Looper.getMainLooper().post(new Runnable(...))
because Looper.getMainLooper() is a static variable and initialized in ActivityThread.
2) if your runnable code snippet is inside an activity
then you can use:
MainActivity.this.runOnUiThread(...)
For those who are looking for an easy instant solution follow the simple steps
Make a reference of your class before your onCreate() method
MyClass obj;
Initialize it in you onCreate() method
obj = MyClass.this;
Call runOnUiThread()
obj.runOnUiThread(new Runnable() {
public void run() {
//perform your UI tasks here
}
});
Hope it helps.
I am ultimately trying to unit test a custom base adapter, but I am stuck at one point: I am unable to figure out how to get the UI thread to process the message I have just passed to it via sendEmptyMessage(...).
In my Activity I have a "addFoo(Foo foo)" method that updates an array and then calls "sendEmptyMessage(1)", and I have a handleMessage method that calls the ListView's adapter to tell it the data has changed.
I've boiled the unit test down to, roughly:
public void testAddFoo() {
Foo foo = new Foo();
assertTrue(mActivity.addFoo(foo));
assertTrue(mActivity.getHandler().hasMessages(1));
assertFalse(mActivity.getHandler().hasMessages(1));
assertTrue(mActivity.fooListNotEmpty());
}
Naturally it is failing on that assertFalse() (this is a contrived example, simplifying it as best as I can).
What call can I make in to mActivity or its handler or looper to get it to process all pending messages? I have tried some suggestions I've read about calling Looper.loop(), within the UI thread, but those are stabs in the dark and they failed.
FWIW, I'm pretty sure that the handleMessage code is correct because if I call it directly (inside #UiThreadTest) like so:
#UiThreadTest
public void testAddFoo() {
Foo foo = new Foo();
assertTrue(mActivity.addFoo(foo));
Message msg = Message.obtain();
msg.what = 1;
mActivity.handleMessage(msg);
assertTrue(mActivity.fooListNotEmpty());
}
the test ends up working as expected.
If your Activity implements Handler.Callback and you want messages to show up in your handleMessage method, then you need to pass in your Activity when you initialize the Handler in onCreate.
mHandler = new Handler(this);
I know you got the member Handler approach working, but I'm adding this for people like me who show up here trying to figure out how to get the Handler.Callback interface approach working.
If you are implementing Handler.Callback in your activity then you should just do
assertTrue(mActivity.hasMessages(1));
otherwise do not implement the callback and use
mHandler = new Handler() {
// override Handler methods as required
// ie handleMessage(Message msg)
};
and
assertTrue(mActivity.mHandler.hasMessages(1));