浮點數引發的Canvas繪製血案

2021-08-06 03:18:41 字數 1202 閱讀 5995

今天在android專案開發中遇到乙個比較有趣的奔潰問題,感覺也好久沒有寫文章了,覺得可以跟大家分享一下的。這個問題涉及到浮點數計算、view繪製流程和機制,理清楚後發現問題其實很簡單。

1.2.1 下面簡單拆解一下其實現:

??????為什麼僅僅設定了乙個view的visibility就會導致閃退呢??????

??????為什麼閃退的時候看不到有奔潰日誌??????

1.2.2 部分關鍵**簡要回顧:

protected

void

onconfigurationchanged(configuration newconfig)

或許很多人可能一看**就能很清楚明了發現問題了,不過下面還是容我分析一般。

那麼,問題是否是因為getwidth()==0導致除的時候拋異常能?

答案肯定是否定的,如果除的時候拋異常,那麼橫豎屏切換的時候就奔潰了,而不是等到tab1的setvisibility才奔潰。

這裡就牽扯出乙個關於浮點數計算的問題了:浮點數計算的時候,此處除以0,事實上得到的結果是乙個正無窮或者負無窮。

所以,並不是除以0導致的異常。(其實雖然不會異常但得到乙個正無窮或者負無窮的值,之後在使用的時候肯定也會有問題)

其實,可以發現,當mscalerate為無窮的時候,這個語句在canvas繪製的肯定會出問題。

但是,為什麼橫豎屏切換的時候明明就已經觸發了invalidate但是並沒有卡死奔潰?

這裡就牽扯出view繪製機制的問題了:當檢視不可見(gone)的時候呼叫invalidate是不會觸發draw的。

所以,等到tab1切回了可視(visible)重繪的時候才會跑到dispatchdraw,這個時候canvas.scale處理乙個無窮大的值,你說會不會有問題?

1.橫豎屏切換的時候給view設定了乙個非法數值(無窮大)。

2.切tab觸發view的draw的時候使用了這個非法數值進行了canvas繪製。

tab1不可見的時候不監聽處理onconfigurationchanged。

當getwidth為0的時候不應該做下一步處理。

dispatchdraw中對mscalerate做非法值校驗。

最後,如果覺得我闡述的不夠詳細的,歡迎補充。

浮點數的儲存以及 浮點數的比較

浮點數的儲存採用的是近似的原理 float儲存格式為 s e m 1位符號位 8位指數 23位尾數 轉成數值即為 v 1 s 1.m 2 e 127 對於16.5轉成二進位制為00010000.1 1.00001 2 4,那麼在記憶體的表示為 符號位 指數4 127 131 尾數 0 1000001...

由乙個浮點數引發的思考

下面這段 輸出值是多少呢?void main 在我32位的虛擬機器上,列印輸出值是 data 266270.84 為什麼會出現這種情況呢,難道是計算機出問題了。當然不是計算機出現了問題,我們從下面幾點來分析 首先,我們從浮點數在記憶體中的儲存形式來分析。大家都知道,資料在記憶體中是以010101這種...

浮點數的儲存

浮點數在計算機中的儲存格式 符號位 指數字 尾數字 符號位 指數字 尾數字 float 1位 8位 23位 共32位 double 1位 11位 52位 共64位 任何浮點數都可表示為 1.m 2e 符號位 sign 表示式中的 0表示正數,1表示負數。指數字 exponent 表示式中的e,指數字...