Java 执行顺序与Thread.sleep的使用混淆

Java 执行顺序与Thread.sleep的使用混淆,java,android,sleep,thread-sleep,Java,Android,Sleep,Thread Sleep,我正在为我的android应用程序编写一个方法,其中我使RecyclerView不可见,ProgressBar可见。然后,在将两个视图重置为其原始可见性状态之前,我执行一些逻辑 只需调用setVisibility()即可按预期工作。但是,我还需要调用Thread.sleep(),以便在执行逻辑后直接强制等待 起初,我在尝试调用setVisibility()时遇到了问题。它什么也没做。我发现很多问题都有类似的问题,但还不够相似;我无法找到解决我问题的具体办法 创建一个新方法来简单地调用setVis

我正在为我的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,但所有的参考资料都确切地表明了我所学到的东西;当它执行时,它会强制进程“休眠”一段时间。它不应该强迫方法推迟所有其他逻辑,直到它返回。相反,提供表明正常操作的逻辑和输出

我知道我永远不应该真正调用
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()
一无所知,但是我理解了它的其余部分,并且用一个替代实现解决了我的问题,比我能够学习如何正确实现您的建议要快得多+非常感谢你给我指明了正确的方向。