Java 执行顺序与Thread.sleep的使用混淆
我正在为我的android应用程序编写一个方法,其中我使RecyclerView不可见,ProgressBar可见。然后,在将两个视图重置为其原始可见性状态之前,我执行一些逻辑 只需调用Java 执行顺序与Thread.sleep的使用混淆,java,android,sleep,thread-sleep,Java,Android,Sleep,Thread Sleep,我正在为我的android应用程序编写一个方法,其中我使RecyclerView不可见,ProgressBar可见。然后,在将两个视图重置为其原始可见性状态之前,我执行一些逻辑 只需调用setVisibility()即可按预期工作。但是,我还需要调用Thread.sleep(),以便在执行逻辑后直接强制等待 起初,我在尝试调用setVisibility()时遇到了问题。它什么也没做。我发现很多问题都有类似的问题,但还不够相似;我无法找到解决我问题的具体办法 创建一个新方法来简单地调用setVis
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,但所有的参考资料都确切地表明了我所学到的东西;当它执行时,它会强制进程“休眠”一段时间。它不应该强迫方法推迟所有其他逻辑,直到它返回。相反,提供表明正常操作的逻辑和输出
我知道我永远不应该真正调用Thread.sleep()
,但这是我为大学完成的练习的直接要求。为什么Thread.sleep()
会强制自己在任何其他命令之前运行,尽管它位于方法的末端?更改可见性(或任何其他布局/绘图操作)不会对用户界面产生任何即时同步影响。相反,实际上只是在UI线程的消息队列上发布一条消息,以便稍后处理更改
在UI线程上调用sleep()
是不允许的。您正在阻止UI线程,执行不会返回到消息处理程序,该处理程序将处理队列中等待的重新发布/重画消息。只有在执行sleep()
之后,执行才会返回到消息处理程序
如果需要为代码添加延迟,请使用例如
Handler#postDelayed()
将自己的Runnable
发布到UI线程的消息队列中,以便在延迟后执行 根据@laalto的答案,我决定在研究处理程序#postDelayed()
之前,以异步任务的形式测试我的方法(这是我们没有讨论过的,我对它完全不熟悉)。我很高兴地报告,它完全按照预期工作
对于那些更熟悉实现AsyncTask
的人来说,这可能是一个合适的选择
首先,我实现了一个内部异步类,如下所示:
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);
}
}
私有类RefreshTimesAsyncTask扩展了AsyncTask{
私人长时间;
公共刷新时间异步任务(长睡眠时间){
mSleepTime=睡眠时间;
}
@凌驾
受保护的void onPreExecute(){
mMainProgressBar.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
mTrainAdapter.RefreshAll();
}
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
线程。睡眠(mSleepTime);
}捕获(中断异常异常){
// ...
Thread.currentThread().interrupt();
}
返回null;
}
@凌驾
受保护的void onPostExecute(void结果){
mMainProgressBar.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
}
}
然后我只需调用newRefreshTimesAsyncTask(sSleepTime).execute()代码>,而不是我以前调用的setmain invisible()
。我还在主类的变量声明中设置了static long sSleepTime=3000
,这是因为需要将此值设置为static
,并且不能在内部类中声明static
变量。干杯。老实说,我对处理程序#postdayed()
一无所知,但是我理解了它的其余部分,并且用一个替代实现解决了我的问题,比我能够学习如何正确实现您的建议要快得多+非常感谢你给我指明了正确的方向。