线程随着时间的流逝而变慢

时间:2018-09-08 13:20:11

标签: android textview spannable

我正在尝试制作一个彩虹色的标题(随时间变化),这是onCreate:

protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_menu);

    new Thread(TitleColorRunnable).start();

}

与之对应的可运行文件:

Runnable TitleColorRunnable = new Runnable()
{
    TextView title;
    int titleLength;
    Spannable spannable;
    int i;
    float mainHue = 15;
    float hue;
    int color;

    @Override
    public void run()
    {
        title = findViewById(R.id.titleTextView);
        title.setText("TITLE EXAMPLE", TextView.BufferType.SPANNABLE);
        titleLength = title.length();
        spannable = (Spannable) title.getText();

        while (true)
        {
            for (i = 0; i < titleLength - 1; i++)
            {
                hue = (mainHue - i) % 360;
                color = Color.HSVToColor(new float[]{hue, 1, 1});

                title.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        spannable.setSpan(new ForegroundColorSpan(color), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                });
            }

            mainHue++;
            if (mainHue == 360)
            {
                mainHue = 0;
            }

            try
            {
                Thread.sleep(10);
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
};

该线程会随着时间的流逝而变慢,并开始缓慢地调试整个UI,直到一切完全停止。

这行可能吗

spannable.setSpan(new ForegroundColorSpan(color), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

是否将新的ForegroundColorSpan变量保存到内存?

请帮助,谢谢!

1 个答案:

答案 0 :(得分:0)

参考该行:

title.post(new Runnable()...

我们无法保证下次您致电title.post()时,Runnable已完成并已出队。应用程序Looper中的Runnables队列可能正在超级积压。 IOW,您对Runnable的排队速度比其可执行的速度快,最终您的UI线程必须花所有的时间来处理它们,而不是做您想做的其他事情,例如响应用户输入和等等。

一个影响因素是您的10毫秒延迟:Thread.sleep(10)。对于这种更新,100Hz有点快。 30Hz应该足够(以供人类感知),甚至更慢,因为您只是勉强改变颜色。

建议的修补程序

  • 摆脱线程。采用您的TitleColorRunnable逻辑,并将其移至onCreate()
  • 声明您的Runnable-您现在作为封闭对象的Runnable,作为最终的局部变量。
  • 在您的myRunnable.run()内,执行title.postDelayed( myRunnable, 33 )。这是窍门;这是使迭代继续进行的原因,也是阻止Looper队列填满的原因。由于myRunnable重新排队 ,因此队列中的myRunnable永远不会超过一个。 (这不是递归;您只是利用Android消息队列机制来调度Runnable。)33ms是30Hz的更新速率。
  • 要开始整个过程​​,请将title.post( myRunnable )添加到onCreate()
  • 改为使用mainHue = mainHue + 3;,以使颜色变化的速率大致相同。

很显然,使用此解决方案,您必须在mainHue内更改myRunnable.run()的状态。