今天在写 Android 的时候,用到了 ProgressDialog 这个进度提示框,我把 progress 提前 new 出来,并在子线程开始之前把它 show 出来。这里我的子线程是 new 了一个 runnable 来实现的,在子线程做完耗时工作的最后,调用 progress 的 dismiss 方法。但是很奇怪,直到子线程结束,进度框都没有显示出来。开始我以为是子线程的耗时太短,根本来不及显示就隐藏掉了。我又让子线程里每循环一次睡上 0.1 秒,但是还是不能显示。我又注释了隐藏进度条的逻辑,这个时候才发现子线程执行完毕之后进度条才显示出来,所以之前其实是子线程执行完毕后才显示进度条,但是又立刻被关闭掉了,以至于我根本观察不到。但这样我还是不知道是什么导致了进度条在子线程执行完了才显示。下面是我开始用 runnable 的代码:
1 | final ProgressDialog progressDialog = new ProgressDialog(ProToolsActovoty.this); |
我也是知道 Thread 和 runnable 在某些条件下是可以通用的,不过脑海中总是隐约记得要优先使用 runnable 而不是 Thread 。所以 runnable 不对头,只好去试试 Thread 了。不过这一试还确实试对了,使用 Thread 来开启子线程的结果也是我所预期的。在子线程开始之前显示进度条,子线程结束之后隐藏,还是 Thread 大法好呀。但仅仅知道怎么做是正确的还不够,必须得知道为什么要这么做呢?只有了解了 runnable 和 Thread 的区别,才能真的算是会使用。
然而当我开始试图分清楚 runnable 和 Thread 的区别的时候,我发现我一开始就错了,因为 runnable 只是一个接口啊,即使我通过 runnable 创建了一个实例,它仍然只是个接口,并非一个真正意义上的子线程。为了验证我的想法,新建一个小例子:
1 | public class RunnableTest { |
我用之前的办法创建了一个 runnable 的实例,并分别在这个实例中和主线程中打印了当前的线程 ID ,结果:
1
1
两个线程 ID 完全一致,所以 runnable 并没有在子线程中执行,只不过是相当于在主线程中调用了 runnable 的 run 方法而已。可即便如此,作为一个方法,它也无法阻止进度条的显示吧。这里我暂时还不能得出结论,先当做一个疑问留下来,如果有读者了解也欢迎留言一起探讨。
正确是的使用 runnable 接口的方法是在一个新的 Thread 中传入 runnable 接口,像这样:
1 | new Thread(new Runnable() { |
尽管程序已经能够正确运行,但是我还是不知道我之前的错误是如何发生的,也不明白其中的原理,不过现在不明白,不代表将来也还是不明白,最近我会多多研究多线程以及 ProgressDialog 的深入解析,争取搞清楚其中的门道。