我正在尝试制作一个彩虹色的标题(随时间变化),这是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变量保存到内存?
请帮助,谢谢!
答案 0 :(得分:0)
参考该行:
title.post(new Runnable()...
我们无法保证下次您致电title.post()
时,Runnable已完成并已出队。应用程序Looper中的Runnables队列可能正在超级积压。 IOW,您对Runnable的排队速度比其可执行的速度快,最终您的UI线程必须花所有的时间来处理它们,而不是做您想做的其他事情,例如响应用户输入和等等。
一个影响因素是您的10毫秒延迟:Thread.sleep(10)
。对于这种更新,100Hz有点快。 30Hz应该足够(以供人类感知),甚至更慢,因为您只是勉强改变颜色。
建议的修补程序
TitleColorRunnable
逻辑,并将其移至onCreate()
。myRunnable.run()
内,执行title.postDelayed( myRunnable, 33 )
。这是窍门;这是使迭代继续进行的原因,也是阻止Looper队列填满的原因。由于myRunnable
重新排队 ,因此队列中的myRunnable
永远不会超过一个。 (这不是递归;您只是利用Android消息队列机制来调度Runnable。)33ms是30Hz的更新速率。title.post( myRunnable )
添加到onCreate()
。mainHue = mainHue + 3;
,以使颜色变化的速率大致相同。很显然,使用此解决方案,您必须在mainHue
内更改myRunnable.run()
的状态。