關於坑爹的PopupWindow的“阻塞”爭議問題:Android沒有真正的“阻塞式”對話框

請先允許我對網上某些沒經過親自實踐人云亦云的同志呵呵。。。

那麼開始正文,首先“阻塞”這個詞本身就存在理解上的差異!

一般我們理解的阻塞,是阻塞了某個線程,即代碼執行到這裏後等待這個函數塊執行完畢,才能繼續向下運行。比如常見的控制檯輸入函數,必須要求用戶輸入一個值才能繼續,否則等待。

而在Android裏,一部分人對阻塞做了另外的解釋:鎖死了其它UI,只有當前這個模塊可以被響應。具體什麼意思呢?比如原本點擊屏幕,會彈出一個Toast。那麼好,現在我彈出一個UI,用戶只能在這個UI操作,他再去點擊這個UI外圍的屏幕,將觸發不了“彈出Toast”這個事件,那麼就認爲這個UI“阻塞”了應用。

好,現在我們着重分析第二種看法。乍一看貌似沒問題,原本應該執行的操作,因爲另一個操作沒結算完畢而不能發生,這不就是“阻塞”了麼?然而事實是,這種“阻塞”實質上只是屏蔽了控制彈出Toast的代碼塊的觸發條件:點擊UI。準確的說,是把點擊UI這個操作給截獲了。但如果這個事件是在這個線程裏順序執行的,他並不需要事件驅動呢?想要測試也很簡單,探出一個PopupWindow,緊接着在下面(不是某個UI的監聽器裏)寫一個Log.v();呵呵噠,看到了吧,不等你關掉彈窗,Log.v裏面的內容已經被打印了。。。

可見,PopupWindow的“阻塞”,其實只是一種屏蔽。它僅僅是使得其它控件不可被操作罷了。說它是“阻塞的”,沒問題,就是容易誤導;但說它是“線程阻塞”的就呵呵了。另外面對這個問題,網上還有一種退而求其次的建議:把要做的東西放到onClick();裏面。這樣也能一定程度的解決問題,但需要把原本連貫的一個過程拆分開。雖然不可否認,這本就更符合Android的設計框架的思想,但如果是在流程已經設計好了,無法改動的情況下就行不通了。

總結:PopupWindow的”阻塞”並不能使你的線程wait。它完全取得了用戶操作的響應處理權限,從而使其它UI控件不被觸發,僅此而已。無論AlertDialog還是PopupWindow,都不能做到傳統意義上的線程阻塞。想要根據用戶的某個操作來決定程序流程(否則不繼續執行),只能把主線程wait掉。但這樣會導致ANR,所以取巧的方法是while([某個值沒有被改變]) sleep(100);是的,間歇性sleep主線程,告訴Android,咱每100ms有一次響應,你別給我ANR了啊。

附上我的小遊戲的源碼鏈接,就是在這裏面遇到的問題: GitHub

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章