执行顺序与 Thread.sleep 的使用混淆
order of execution mixed up with use of Thread.sleep
我正在为我的 android 应用程序编写一个方法,我在其中使 RecyclerView 不可见,而 ProgressBar 可见。然后我执行一些逻辑,然后将两个视图重置为其原始可见性状态。
只需 setVisibility()
调用,它就会按预期工作。但是,我也需要在执行完逻辑后直接调用Thread.sleep()
强制等待
最初,我在尝试调用 setVisibility()
时遇到了问题。它什么也没做。我发现很多类似问题的问题,但不够相似;我找不到针对我的问题的解决方案。
创建一个简单调用 setVisibility()
的新方法,我发现它按预期工作。我开始逐行移动我的逻辑,直到它停止工作。
就目前而言,它仍然技术上正确设置可见性。然而,尽管从 setVisibility()
调用向下几行,我的 Thread.sleep()
似乎在 setVisibility()
之前强迫自己到 运行。我相信这是我最初的问题;从逻辑上讲,Thread.sleep()
之后的命令将直接在 运行 之后,并有效地在下一帧撤消我的 setVisibility()
。
这是我的方法:
public void SetMainInvisible(){
mRecyclerView.setVisibility(View.INVISIBLE);
mMainProgressBar.setVisibility(View.VISIBLE);
mTrainAdapter.RefreshAll();
Log.d("TEST", "FINISHED VIS");
try {
Thread.sleep(sSleepTime);
} catch (InterruptedException exception) {
// In the nature of a simple "Thread.sleep", there is no real reason to respond
// directly to interruption. If the sleep request is interrupted, the best course
// of action to preserve user experience is to simply move on. That said, we will
// still "re-enable" the flag that tells us the thread was interrupted, in case we
// should need to clarify if there was an interruption, later on. As is, this flag
// will be reset to false as soon as the exception is thrown.
Thread.currentThread().interrupt();
}
}
根据我的直接观察,当它调用时,我的日志会打印 "FINISHED VIS"。然后我的应用程序进入 Thread.sleep()
阶段,并等待 3 秒。然后我的视图改变了它们的可见性,按照第一行 的指示。我的代码中没有其他地方 setVisibility()
。
我已经尝试进一步阅读 Thread.sleep,但所有参考资料都准确地表明了我所学的内容;当它执行时,它会强制进程 "sleep" 一段时间。它不应该强制该方法推迟所有其他逻辑直到它returns。相反,the examples at Tutorial Point 提供建议正常操作的逻辑和输出。
我知道我永远不应该打电话给 Thread.sleep()
,但这是我为大学完成的练习的直接要求。为什么 Thread.sleep()
在任何其他命令之前强制自己 运行,尽管它处于方法的 end?
更改可见性(或任何其他 layout/drawing 操作)不会对您的用户界面产生任何即时、同步的影响。相反,实际上只是 post 在 UI 线程的消息队列中编辑了一条消息,以便稍后处理更改。
禁止在 UI 线程上调用 sleep()
。您正在阻塞 UI 线程,并且执行不会 return 处理队列中等待的 relayout/redraw 消息的消息处理程序。只有在 sleep()
之后才会对消息处理程序执行 return。
如果您需要在代码中添加延迟,请使用例如Handler#postDelayed()
到post一个自己的Runnable
到UI线程的消息队列,延迟后执行。
根据@laalto 的回答,我决定在研究 Handler#postDelayed()
之前以 AsyncTask
的形式测试我的方法(这是我们没有涉及的内容,我完全不熟悉用它)。我很高兴地报告它完全按预期工作。
对于那些更熟悉实施 AsyncTask
的人来说,这可能是一个合适的选择。
首先,我实现了一个内部异步class如下:
private class RefreshTimesAsyncTask extends AsyncTask<Void, Void, Void> {
private long mSleepTime;
public RefreshTimesAsyncTask (long sleepTime) {
mSleepTime = sleepTime;
}
@Override
protected void onPreExecute() {
mMainProgressBar.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
mTrainAdapter.RefreshAll();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException exception) {
// ...
Thread.currentThread().interrupt();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mMainProgressBar.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
}
}
然后我简单地调用 new RefreshTimesAsyncTask(sSleepTime).execute();
,而不是我之前的 SetMainInvisible()
函数调用。由于需要将此值设置为 static
和 [=27= 的性质,我还在我的 main class 的变量声明中设置了 static long sSleepTime=3000
]not 无法在内部 class.
中声明 static
变量
我正在为我的 android 应用程序编写一个方法,我在其中使 RecyclerView 不可见,而 ProgressBar 可见。然后我执行一些逻辑,然后将两个视图重置为其原始可见性状态。
只需 setVisibility()
调用,它就会按预期工作。但是,我也需要在执行完逻辑后直接调用Thread.sleep()
强制等待
最初,我在尝试调用 setVisibility()
时遇到了问题。它什么也没做。我发现很多类似问题的问题,但不够相似;我找不到针对我的问题的解决方案。
创建一个简单调用 setVisibility()
的新方法,我发现它按预期工作。我开始逐行移动我的逻辑,直到它停止工作。
就目前而言,它仍然技术上正确设置可见性。然而,尽管从 setVisibility()
调用向下几行,我的 Thread.sleep()
似乎在 setVisibility()
之前强迫自己到 运行。我相信这是我最初的问题;从逻辑上讲,Thread.sleep()
之后的命令将直接在 运行 之后,并有效地在下一帧撤消我的 setVisibility()
。
这是我的方法:
public void SetMainInvisible(){
mRecyclerView.setVisibility(View.INVISIBLE);
mMainProgressBar.setVisibility(View.VISIBLE);
mTrainAdapter.RefreshAll();
Log.d("TEST", "FINISHED VIS");
try {
Thread.sleep(sSleepTime);
} catch (InterruptedException exception) {
// In the nature of a simple "Thread.sleep", there is no real reason to respond
// directly to interruption. If the sleep request is interrupted, the best course
// of action to preserve user experience is to simply move on. That said, we will
// still "re-enable" the flag that tells us the thread was interrupted, in case we
// should need to clarify if there was an interruption, later on. As is, this flag
// will be reset to false as soon as the exception is thrown.
Thread.currentThread().interrupt();
}
}
根据我的直接观察,当它调用时,我的日志会打印 "FINISHED VIS"。然后我的应用程序进入 Thread.sleep()
阶段,并等待 3 秒。然后我的视图改变了它们的可见性,按照第一行 的指示。我的代码中没有其他地方 setVisibility()
。
我已经尝试进一步阅读 Thread.sleep,但所有参考资料都准确地表明了我所学的内容;当它执行时,它会强制进程 "sleep" 一段时间。它不应该强制该方法推迟所有其他逻辑直到它returns。相反,the examples at Tutorial Point 提供建议正常操作的逻辑和输出。
我知道我永远不应该打电话给 Thread.sleep()
,但这是我为大学完成的练习的直接要求。为什么 Thread.sleep()
在任何其他命令之前强制自己 运行,尽管它处于方法的 end?
更改可见性(或任何其他 layout/drawing 操作)不会对您的用户界面产生任何即时、同步的影响。相反,实际上只是 post 在 UI 线程的消息队列中编辑了一条消息,以便稍后处理更改。
禁止在 UI 线程上调用 sleep()
。您正在阻塞 UI 线程,并且执行不会 return 处理队列中等待的 relayout/redraw 消息的消息处理程序。只有在 sleep()
之后才会对消息处理程序执行 return。
如果您需要在代码中添加延迟,请使用例如Handler#postDelayed()
到post一个自己的Runnable
到UI线程的消息队列,延迟后执行。
根据@laalto 的回答,我决定在研究 Handler#postDelayed()
之前以 AsyncTask
的形式测试我的方法(这是我们没有涉及的内容,我完全不熟悉用它)。我很高兴地报告它完全按预期工作。
对于那些更熟悉实施 AsyncTask
的人来说,这可能是一个合适的选择。
首先,我实现了一个内部异步class如下:
private class RefreshTimesAsyncTask extends AsyncTask<Void, Void, Void> {
private long mSleepTime;
public RefreshTimesAsyncTask (long sleepTime) {
mSleepTime = sleepTime;
}
@Override
protected void onPreExecute() {
mMainProgressBar.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
mTrainAdapter.RefreshAll();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException exception) {
// ...
Thread.currentThread().interrupt();
}
return null;
}
@Override
protected void onPostExecute(Void result) {
mMainProgressBar.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
}
}
然后我简单地调用 new RefreshTimesAsyncTask(sSleepTime).execute();
,而不是我之前的 SetMainInvisible()
函数调用。由于需要将此值设置为 static
和 [=27= 的性质,我还在我的 main class 的变量声明中设置了 static long sSleepTime=3000
]not 无法在内部 class.
static
变量