public class ThreadView extends View {
Paint paint = new Paint();
int count;
Handler uiThread = new Handler();
public ThreadView(Context context, AttributeSet attrs) {
super(context, attrs);
paint.setColor(Color.BLACK);
paint.setTextSize(80);
uiThread.post(new Runnable() {
@Override
public void run() {
while(true) {
count++;
invalidate();
}
}
});
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawText(count + "", 100, 100, paint);
}
}
I saw this solution for threads in custom views, but it did not work. Even though my loop continues to call invalidate()
, it does not continue to call onDraw()
I also saw a solution where they implemented Runnable and overrode run()
is this a better way to do it?
All Views have a handler already set up for them, so it is inefficient to create another one. Instead, you should make use of the View class' post(Runnable action) or postDelayed(Runnable action, long delayMillis) methods.
As far as what you are trying to accomplish, I am making the assumption that the code you provided is just to serve as an example. If you were really just trying to update some text, I'd say go with a TextView and call setText on it. The TextView takes care of invalidating itself when it knows its text has changed.
But back to your question. A lot depends on the rate at which you want to update the rendering of your count variable. You currently will run in an endless loop on the UI Thread. This most certainly will cause problems as you will spam the handler/event queue with invalidate calls while at the same time preventing anything else from running on the UI Thread.
Instead, I'd propose introducing a configurable timing delay, and a way to stop updating the view.
For example, you could set things up to invalidate your view once every 10th of a second and only have the counter update while your view is attached to the window like so (note that the Runnable is itself responsible for whether it should run again based on the value of the updateView flag):