Android应用程序中的非冻结睡眠

NZJ*_*mes 1 android

我正在以编程方式创建一些视觉事件,即在单击按钮时显示图像,然后应等待 500 毫秒,然后以滑动效果将图像从屏幕上扫除。但是,如果我尝试使用 Thread.sleep,它在进入睡眠之前不会处理以前的 UI 事件,因此在这种情况下,图像应设置为可见,然后它会休眠,但它会在图像变得可见之前休眠。此外,移动视图的循环太快了 - 我希望使用 Thread.sleep 来减慢它的速度,但看起来这也行不通。

有什么更好的方法可以做到这一点?

View passImage = frontView.findViewWithTag(SearchConstants.PassImageTag);
passImage.setAlpha((float) 1);
frontView.setRotation((float)-10);

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

for (float i = 0; i > 0 - halfScreenWidth; i--) {
    frontView.setX(i);
}
Run Code Online (Sandbox Code Playgroud)

Xav*_*ler 6

永远不要使用Thread.sleep(). 如果你这样做,你正在阻止当前的Thread. 这意味着如果您调用Thread.sleep()UI Thread,UI 将冻结并且您无法再与它交互,就像您所经历的那样。有多种选项可以为将来安排某些任务或事件。你可以:

  1. 用一个 Timer
  2. 用一个 HandlerpostDelayed()
  3. 使用 AlarmManager

用一个 Timer

Timer 可用于安排 TimerTask. 它们最适合在未来几秒钟到几分钟内安排任务。

首先你必须写一个TimerTask. 该任务将在时间过去后执行。ATimerTask可能看起来像这样:

private class ExampleTask extends TimerTask {

    @Override
    public void run() {
        // This method is called once the time is elapsed   
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以安排TimerTask这样的:

Timer timer = new Timer();
ExampleTask task = new ExampleTask();

// Executes the task in 500 milliseconds
timer.schedule(task, 500); 
Run Code Online (Sandbox Code Playgroud)

用一个 HandlerpostDelayed()

使用 aHandler与使用 a非常相似Timer,但我个人更喜欢使用 aTimer因为它们更适合这样的工作。Handler最初是为了方便Threads与其他事物之间的通信,但它们也可用于调度Runnable. 首先我们必须定义一个Runnable,这非常类似于TimerTask

Runnable runnable = new Runnable() {

    @Override
    public void run() {
        // This method will be executed in the future
    }
};
Run Code Online (Sandbox Code Playgroud)

现在我们安排Runnable将来执行postDelayed()

Handler handler = new Handler();

// Execute the Runnable in 500 milliseconds
handler.postDelayed(runnable, 500);
Run Code Online (Sandbox Code Playgroud)

使用 AlarmManager

AlarmManager是一个系统服务,可用于Intent在未来的某个时候发送一个。您可以Intent使用AlarmManager,唯一的缺点是您必须在手机重新启动时重置所有警报。

你可以得到AlarmManager这样的:

AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Run Code Online (Sandbox Code Playgroud)

您还需要将Intent要发送的包裹在一个PendingIntent

Intent intent = new Intent(SOME_ACTION);
...  // Setup your intent
PendingIntent pendingIntent = PendingIntent.getService(context, REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Run Code Online (Sandbox Code Playgroud)

您可以安排Intent在特定的时间发送,Date如下所示:

manager.set(AlarmManager.RTC, date.getTime(), pendingIntent);
Run Code Online (Sandbox Code Playgroud)