在自定义视图中使用线程

Der*_*son 0 multithreading android android-custom-view

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我在自定义视图中看到了针对线程的此解决方案,但是没有用。即使我的循环继续调用invalidate(),也不会继续调用,onDraw() 我还看到了一个解决方案,他们在其中实现了Runnable并覆盖了run(),这是一种更好的方法吗?

Mic*_*use 5

所有视图均已为其设置了处理程序,因此创建另一个视图效率很低。相反,您应该使用View类的post(Runnable action)或postDelayed(Runnable action,long delayMillis)方法。

至于您要完成的工作,我假设您提供的代码仅作为示例。如果您真的只是想更新某些文本,我会说使用TextView并在其上调用setText。当TextView知道其文本已更改时,它负责使自身失效。

但是回到您的问题。在很大程度上取决于您要更新计数变量的呈现方式的速率。当前,您将在UI线程上无休止地运行。这肯定会引起问题,因为您将使用无效调用向处理程序/事件队列发送垃圾邮件,同时阻止其他任何事情在UI线程上运行。

相反,我建议引入可配置的定时延迟,以及一种停止更新视图的方法。

例如,您可以设置为使视图每隔十分之一秒失效,并且仅在视图附加到窗口时才更新计数器(请注意,Runnable本身负责根据是否根据以下条件再次运行该视图) updateView标志的值):

public class ThreadView extends View {

    private class UpdateViewRunnable implements Runnable {
        public void run() {
            count++;
            invalidate();

            if (updateView) {
                postDelayed(this, DELAY_TIME_MILLIS);
            }
        }
    }

    private static final long DELAY_TIME_MILLIS = 100L;
    private boolean updateView = false;
    private UpdateViewRunnable updateViewRunnable = new UpdateViewRunnable();
    private Paint paint = new Paint();
    private int count;

    public ThreadView(Context context) {
        super(context);
        init(context, null);
    }

    public ThreadView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        paint.setColor(Color.BLACK);
        paint.setTextSize(80);
    }

    @Override
    public void onDraw(Canvas canvas) {
        canvas.drawText(count + "", 100, 100, paint);
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        updateView = true;
        postDelayed(updateViewRunnable, DELAY_TIME_MILLIS);
    }

    @Override
    public void onDetachedFromWindow() {
        updateView = false;
        super.onDetachedFromWindow();
    }
}
Run Code Online (Sandbox Code Playgroud)