I'm implementing my own SurfaceView which contains a Thread object whose purpose is to draw various graphical objects to the Canvas. In the constructor of my SurfaceView, I set up the objects to be drawn and the Thread object (currently) only positions them to the Canvas as appropriate.
I have need now to change one of the objects created in the constructor of my SurfaceView (the object is a Bitmap) after the user has performed a particular action (i.e. the Thread object is running). This means communication between the app's GUI thread and the thread executing my Thread object. I discovered this page which details the use of the HandlerThread class, perfect for what I need to achieve. However I need to be sure of how this class works to ensure there is no memory consistency errors.
The following is psuedo code of my own class with a lot stripped out for clarity:
public MyThread extends Thread {
boolean _run = true;
public void run(){
// Create HandlerThread object
// Create Looper object
// Create Handler object
while (_run){
// DRAW the Bitmap in this loop
}
}
public boolean handleMessage(Message message){
/*
ALTER the Bitmap here as required
*/
}
}
public MyThread extends Thread {
boolean _run = true;
public void run(){
// Create HandlerThread object
// Create Looper object
// Create Handler object
while (_run){
// DRAW the Bitmap in this loop
}
}
public boolean handleMessage(Message message){
/*
ALTER the Bitmap here as required
*/
}
}
As I understand it the handleMessage() method is executed by the same thread executing the run() method. However because handleMessage() ALTERS the the Bitmap whereas run() DRAWS the bitmap. Can I be sure that handleMessage() will complete in its entirety before the thread returns to the run() method?
Not sure if i understand the question??
you're extending a regular Thread class in both cases, which don't inherently do anything special. process execute in serialized fashion unless you otherwise specified run and handleMessage to be run from different CALLING threads. so my guess is yes. that should be a fairly straightforwards thread safe execution pattern - if you're calling handleMessage and run in the same thread, then there's not reason they shouldn't be synchronized. if you're calling the two methods from different threads, (or if you're super worried and can't find the answer anywhere else), you can always lock on an object monitor by using synchronized(myLock) in both methods like:
public MyThread extends Thread {
boolean _run = true;
public void run(){
synchronized(this) {
while (_run){
// DRAW the Bitmap in this loop
}
}
}
public boolean handleMessage(Message message){
synchronized(this){...}
}
}
Related
I have one thread that does lot of time consuming tasks. The tasks are being done in the native part in c++. I would like to cancel the operation that is being done in the native, the code for that is place. I can reset everything.
mWorker = new WorkerThread("Worker thread");
mWorker.start();
//From Main thread:- Interrupting
mWorker.interrupt();
if(mWorker.isInterrupted()) {
Log.i(MOD_TAG, "Worker thread is interupptedd!!! ");
}
//Worker thread
public class WorkerThread extends Thread implements Runnable{
public void run() {
while(!Thread.currentThread().isInterrupted()) {
Looper.prepare();
mHandler = new WorkerHandler();
Looper.loop();
}
class WorkerHandler extends Handler {
#Override public void handleMessage(Message msg) {
try {
switch(msg.what) {
//do something native code
}
}
catch (Exception e) {}
}
}
}
}
Even if the workerthread is interrupted I cannot send any message to the worker thread while the worker thread is doing processing. Can I do something to post a message to workerthread or do something else that could let me call a native method within the same thread.
In your example, I don't understand what that Handler is doing inside the Thread. Once you call loop() within the run, that call will block until the looper is stopped via quit() or quitSafely(). The call is basically just a loop which reaps a queue for messages. Your check for interrupt will never happen.
I would recommend something like this. If you want your code to be managed by a handler you would do something like:
HandlerThread handlerThread = new HandlerThread("NativeHandler");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
public void handleMessage(Message msg) {
someObject.callNativeLongRunningFuction();
}
};
However interrupt still won't do anything because the looper only handles one message at a time. So if it is stuck handling callNativeLongRunningFunction(), that is not going to help you really either. If you want to have interrupt stop the ongoing execution of the jni call, the I don't think this approach will work at all with the given information. Interrupt in java only sets a flag and when there is a call to wait(), it will throw an exception when that flag is checked and also set. But for a jni call there isn't a call to wait(), the java stack is sort of blocked but it is not in the middle of a wait() either. So unless you check interrupted within the native runtime, that function will continue to run. Overall I am guessing this probably would not be what you really want.
If that is so, I would recommend something like this instead.
public class NativeThreadTask {
public native void start();
public native boolean isRunning();
public native boolean cancel();
}
Inside the native implementation of that class, you would then use a pThread to call your native long running function. Start and Cancel would manipulate that pThread which would run the expensive function in a separate thread. Using pthread_cancel you can interrupt that pthread instance too. This moves the long operation off your thread and out of your runtime, while still allowing you to control when the pthread interrupt mechanism is invoked but over the jni bridge. If you don't even want to interrupt and if the long running native call is iterating over a large amount of data, then it might be worthwhile to have cancel() simply change bool that is evaluated within each iteration of the native function's loop.
So with the given example you could probably do something like this.
NativeThread nativeThread = new NativeThread();
Handler handler = new Handler() {
public void handleMessage(Message message) {
NativeThread nativeThread = (NativeThread)message.obj;
switch(message.what) {
case 0:
if (!nativeThread.isRunning()) {
nativeThread.start();
}
break;
case 1:
if (nativeThread.isRunning()) {
nativeThread.cancel();
}
break;
default:
}
}
};
I am trying to draw points to android canvas slowly. I want to use canvas.drawline function however drawing one point to another i want to have small delay. Can you help me please?
Here's the general pattern:
// PSEUDOCODE
// in a class created in a Looper thread, e.g., the main thread
private final Handler handler = new Handler();
static class DrawTask implements Runnable {
// final fields for start point, end point, number of segments, interval, etc.
// mutable field for progress
// constructor with appropriate params
#Override
public void run() {
// draw the current line segment
if(!finished) {
handler.postDelayed(this, interval);
}
}
}
// in some draw method
handler.post(new DrawTask(...));
You might want to hang onto a reference to the DrawTask so you can cancel it with Handler#removeCallbacks(...) in case it's still running when your activity is paused.
I'm curious whether or not it's possible to call a network process from the UI thread if the method called is in an instance of a Threaded class... pseudo...
class MyNetworkClass extends Thread{
public boolean keepGoing = true;
public void run(){
while(keepGoing);
}
public void doSomeNetworkStuff(){
//do things that are illegal on the UI Thread
}
}
//and then in my Activity...
MyNetworkClass mnc = new MyNetworkClass();
mnc.start();
mnc.doSomeNetworkStuff();
This feels totally illegal to me, but I'm wondering if it is in fact, and if so why?
You actually called the mnc.doSomeNetworkStuff() method from the same thread as mnc.start();.
This is presumably the UI thread, but for sure not the thread which just started with mnc.start;
Consider the situation:
//creates thread object - does not start a new thread yet
Thread thread = new Thread() {
public void run() {}
};
//...
thread.start(); //this actually started the thread
// the `run` method is now executed in this thread.
//However if you called `run` manually as below
thread.run();
// it would be executed in the thread from which you have called it
// assuming that this flow is running in the UI thread, calling `thread.run()`
// manually as above makes it execute in the UI thread.
EDIT:
Just to make things more clear. Consider that you have some static utility class like below:
public static class SomeUtilityClass {
public static void someUtilityMethod(int i) {
Log.i("SomeUtilityClass", "someUtilityMethod: " + i);
}
}
Then somewhere in your code, called from your "main" thread:
new Thread() {
#Override
public void run() {
// 1.
// call the utility method in new thread
SomeUtilityClass.someUtilityMethod(1);
}
}.start();
// 2.
// call the same method from "main" thread
SomeUtilityClass.someUtilityMethod(2);
Notice that Thread#start() exits immediately and you are not guaranteed which call to SomeUtilityClass.someUtilityMethod(); will be executed first.
My app combines a SurfaceView running on its own thread with a bunch of regular Views running on the main application thread. For the most part, this works fine. However, when I try to have something on the SurfaceView's thread trigger a change to one of the UI elements in the main application thread, I get android.View.ViewRoot$CalledFromWrongThreadException.
Is there a right way around this? Should I use an asynctask? Runonuithread()? Or is mixing a SurfaceView on its own thread with other UI elements on the main thread just an inherently bad thing to do?
If my question doesn't make sense, here's pseudocode that may be clearer.
// Activity runs on main application thread
public class MainActivity extends Activity {
RelativeLayout layout;
TextView popup;
MySurfaceView mysurfaceview;
protected void onCreate(Bundle savedInstanceState) {
...
setContentView(layout);
layout.addView(mysurfaceview); // Surface View is displayed
popup.setText("You won"); // created but not displayed yet
}
public void showPopup() {
layout.addView(popup);
}
}
// Surface View runs on its own separate thread
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {
private ViewThread mThread;
public boolean onTouch(View v, MotionEvent event) {
...
if (someCondition == true) {
mainactivity.showPopup();
// This works because onTouch() is called by main app thread
}
}
public void Draw(Canvas canvas) {
...
if (someCondition == true) {
mainactivity.showPopup();
// This crashes with ViewRoot$CalledFromWrongThreadException
// because Draw is called by mThread
// Is this fixable?
}
}
}
You cannot change UI elements from other threads other than the UI thread. However, you can still post commands to the UI thread from another thread to update the elements.
You can do the following:
Instantiate a handler in the UI thread like:
final Handler handler = new Handler();
Then in your other thread, you can post a message to the UI thread to update your view through the handler as follows:
handler.post(new Runnable(){
public void run(){
//Update your view here
}
});
And you should be goos to go. Just remember, you MUST instantiate the handler in the UI thread.
Or
If you are running your other thread inside an Activity instance, you can use:
this.runOnUiThread(new Runnable(){
public void run(){
//your UI update code here
}
});
Should I use an asynctask? Runonuithread()?
Either of these should be fine. I typically use AsyncTask for most things that need to update the UI after doing a background process. But either should work.
AsyncTask Docs
runOnUiThread example and Docs
Why don't you use callback? In MySurfaceView, you can add an interface,
public interface onClickSurfaceView{
public void change();
}
then in your activity implement MySurfaceView.onClickSurfaceView, and you can have a reference to surfaceView. Then call the surfaceView.setListener(this) to register the activity as a subscriber,
and you can call the update your UI in the change() method.
simple answer is you cannot update UI elements from a non-UI thread.
you need to have a callback method or something that calls back to the main thread to update the UI
You need to use this -
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Populate UI
}
});
I'm wondering how Handlers are processed in Android/DalvikVM. I'm writing an application for Android, and in one class I have a Handler method which receives messages from another class. Will the Handler method act as a Thread and be asynchronous to the run() method in the same class, or will it wait until a line of code in the run() method is finished (sort of atomic operation)? Or something else?
I'm wondering, because I want to add messages to a queue in the Handler method, and process and remove them in the run() method (producer-consumer).
My code structure:
public class Parser implements Runnable {
public void run() {
while(true) {
// Remove a byte from the ring buffer and parse it
byte b = Ringbuffer_read();
// Parse
try {
Thread.sleep(40);
} catch (InterruptedException e) {}
}
}
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_READ:
// Store all the received bytes in the ring buffer
for (int i = 0; i < msg.arg1; i++) {
Ringbuffer_store(((byte[]) msg.obj)[i]);
}
break;
}
}
};
}
When will the code in the handler run? Does it interrupt the code in the run() method at any point? Do I have to have some synchronization or semaphores or something around the code in the run() and handler method so that I don't corrupt my buffer?
An Android Handler associates itself with whatever thread it is created in (assuming that thread has a looper already). By default in Android callbacks run on a thread named "main" which is also called the ui thread. Regardless of what thread the post method is called from the handleMessage method will be called from the thread that the Handler was created in (usually the "main" thread). Because the handleMessage method is always called in the same thread, only one message will be processed at a time.
If your plan is to have only a single consumer then Handler is a good choice. You will not need to remove messages from your consumer (the Handler), instead they will simply arrive in handleMessage for processing. If you want to do processing on the "main" thread then you just make a new Handler, if you want to do processing in the background to avoid ANRs you will likely want to use HandlerThread. Here's an example of a Handler running on it's own background thread:
HandlerThread handlerThread = new HandlerThread("Consumer");
handlerThread.start();
Handler consumer = new Handler(handlerThread.getLooper()) {
public void handleMessage (Message msg) {
}
};
Notice that in the description above class does not come into play at all because classes are how code is structured which is unrelated to what thread the code is executed on.