android空指針異常的解決方法為:
成都創(chuàng)新互聯(lián)從2013年開(kāi)始,是專(zhuān)業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元蕪湖縣做網(wǎng)站,已為上家服務(wù),為蕪湖縣各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:18982081108
1、findviewbyid返回值為null
出現(xiàn)findviewbyid返回值為null時(shí),改一下名字就可以,可能是名稱與控件的名稱一樣造成的。
2、location不是馬上就能獲取到的,應(yīng)該判斷一下,空的話就返回,等到下次獲取,模擬機(jī)是獲取不到得,要用真機(jī)。
這個(gè)不是Android的問(wèn)題,而是Java語(yǔ)言基礎(chǔ)內(nèi)容。
1.Java中所謂的指針,是指對(duì)象的引用。比如String str;這個(gè)str就是指針。
2.空指針是說(shuō)指針的內(nèi)容為空,比如上面的str,如果令它指向null,就是空指針。
3.空指針異常就是一個(gè)指針是空指針,你使用了這個(gè)空指針的方法,既然它指向的是空對(duì)象,它就不能使用這個(gè)對(duì)象的方法。比如上面的str假如為null,你還要用str的方法,比如str.equals( String x);那么就會(huì)產(chǎn)生空指針異常。
android中有三種智能指針,分別是輕量級(jí)指針,強(qiáng)指針,弱指針。輕量級(jí)指針實(shí)現(xiàn)簡(jiǎn)潔,效果類(lèi)似于強(qiáng)指針,然后強(qiáng)指針和弱指針的實(shí)現(xiàn)比較復(fù)雜比較重一些。本篇就介紹下這三種指針的具體實(shí)現(xiàn)。
輕量級(jí)指針在Android中是由LightRefBase來(lái)提供的,看下內(nèi)容:
一個(gè)類(lèi)只要繼承LightRefBase,然后配合sp就可以使用智能指針的功能了。sp后面會(huì)單獨(dú)介紹。
從這兒可以看出來(lái),輕量級(jí)指針主要是在類(lèi)里面添加了一個(gè)原子變量作為計(jì)數(shù)變量,然后通過(guò)incStrong和decStrong來(lái)實(shí)現(xiàn)計(jì)數(shù)的增減。
這兒有一個(gè)細(xì)節(jié)是這個(gè)計(jì)數(shù)可能會(huì)在多個(gè)線程里面訪問(wèn),因此就會(huì)出現(xiàn)并發(fā)問(wèn)題。比如一個(gè)對(duì)象對(duì)應(yīng)的多個(gè)智能指針在多個(gè)線程里面使用,這時(shí)候就需要某個(gè)機(jī)制可以保證計(jì)數(shù)的準(zhǔn)確。具體的策略就在incStrong和decStong里面,可以看到主要是使用了原子操作,并指定了內(nèi)存序。這樣通過(guò)內(nèi)存屏障手段實(shí)現(xiàn)了不用持鎖也能實(shí)現(xiàn)一致性。
接下來(lái)看下sp,一個(gè)類(lèi)繼承了LightRefBase后就擁有了智能指針計(jì)數(shù)機(jī)制,然后通過(guò)sp來(lái)操作指針才能實(shí)現(xiàn)智能管理內(nèi)存的效果:
可以看到sp定義了對(duì)指針的基本操作,并通過(guò)m_ptr保存所管理的對(duì)象指針,看下構(gòu)造和析構(gòu)方法:
初始化m_ptr,然后調(diào)用incStrong增加計(jì)數(shù),其實(shí)就是調(diào)用LightRefBase的incStrong,再看下移動(dòng)拷貝構(gòu)造函數(shù):
移動(dòng)只涉及擁有權(quán)的轉(zhuǎn)移,因此不能更新計(jì)數(shù)。
其他構(gòu)造函數(shù)也類(lèi)似,再看下析構(gòu)函數(shù):
析構(gòu)就是減少計(jì)數(shù),調(diào)用LightRefBase的decStrong,看下對(duì)應(yīng)的實(shí)現(xiàn):
對(duì)計(jì)數(shù)減1,如果計(jì)數(shù)已經(jīng)是1了,難么減少后就是0,就需要調(diào)用下析構(gòu),把對(duì)象釋放掉。
強(qiáng)指針和弱指針對(duì)應(yīng)的結(jié)構(gòu)都是RefBase:
可以看到對(duì)于強(qiáng)指針,并不是簡(jiǎn)單用一個(gè)原子變量來(lái)計(jì)數(shù)了,而是使用了weakref_impl,這是一個(gè)weakref_type類(lèi)型,定義如下:
可以看到RefBase提供了更多的能力,一個(gè)類(lèi)繼承了RefBase就可以通過(guò)強(qiáng)指針和弱指針來(lái)使用了。強(qiáng)指針就是前面提到的sp,關(guān)鍵的還是incStrong和decStrong,現(xiàn)在再看下流程, 對(duì)于sp的incStorng,調(diào)用的是RefBase的incStrong
可以看到先增加了弱引用,然后又添加了強(qiáng)引用,不過(guò)這兒并不是增加計(jì)數(shù),而是記錄引用指針,接下來(lái)才是增加計(jì)數(shù),如果不是首次增加就直接返回了,否則會(huì)調(diào)用onFirstRef。這樣如果有類(lèi)想在第一次被引用的時(shí)候做些邏輯就可以使用這個(gè)機(jī)制了。
接下來(lái)看下incWeak和addStrongRef:
看到這兒基本就把添加引用流程走完了,從這兒也可以看出來(lái)弱引用計(jì)數(shù)一定大于等于強(qiáng)引用計(jì)數(shù)。
再看下decStrong,調(diào)用的也是RefBase的decStrong
可以看到decStrong中的邏輯主要就是操作強(qiáng)引用計(jì)數(shù)和弱引用計(jì)數(shù)。再看下移除引用和減少弱引用的實(shí)現(xiàn):
再看下減少弱引用實(shí)現(xiàn):
到了這兒decStrong流程就結(jié)束了,主要就是減少?gòu)?qiáng)弱引用計(jì)數(shù)的值,并且在引用計(jì)數(shù)為0時(shí)按照對(duì)象管理策略進(jìn)行析構(gòu)對(duì)象。
再看下弱指針的實(shí)現(xiàn),弱指針比較復(fù)雜一些:
可以看到2點(diǎn):
m_ptr 保存對(duì)象指針,m_refs負(fù)責(zé)計(jì)數(shù),看下createWeak的實(shí)現(xiàn):
再看下析構(gòu):
再看下promote:
通過(guò)attemptIncStrong嘗試修改強(qiáng)引用計(jì)數(shù):
到了這兒關(guān)于弱指針的內(nèi)容也介紹完了。
最后畫(huà)一個(gè)圖總結(jié)下輕量級(jí)指針,強(qiáng)指針,弱指針的關(guān)系:
Android系統(tǒng)的智能指針(輕量級(jí)指針、強(qiáng)指針和弱指針)的實(shí)現(xiàn)原理分析
1、Android
系統(tǒng)的運(yùn)行時(shí)庫(kù)層代碼是用C++來(lái)編寫(xiě)的,用C++來(lái)寫(xiě)代碼最容易出錯(cuò)的地方就是指針了,一旦使用不當(dāng),輕則造成內(nèi)存泄漏,重則造成系統(tǒng)崩潰。不過(guò)系統(tǒng)提供了智能指針,避免出現(xiàn)上述問(wèn)題;
2、在使用C++來(lái)編寫(xiě)代碼的過(guò)程中,指針使用不當(dāng)造成內(nèi)存泄漏一般就是因?yàn)閚ew了一個(gè)對(duì)象并且使用完之后,忘記了delete這個(gè)對(duì)象,而造成系統(tǒng)崩潰。一般就是因?yàn)橐粋€(gè)地方delete了這個(gè)對(duì)象之后,其它地方還在繼續(xù)使原來(lái)指向這個(gè)對(duì)象的指針。
3、為了避免出現(xiàn)上述問(wèn)題,一般的做法就是使用引用計(jì)數(shù)的方法,每當(dāng)有一個(gè)指針指向了一個(gè)new出來(lái)的對(duì)象時(shí),就對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)增加1,每當(dāng)有一個(gè)指針不再使用這個(gè)對(duì)象時(shí),就對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)減少1,每次減1之后,如果發(fā)現(xiàn)引用計(jì)數(shù)值為0時(shí),那么,就要delete這個(gè)對(duì)象了,這樣就避免了忘記delete對(duì)象或者這個(gè)對(duì)象被delete之后其它地方還
在使用的問(wèn)題了。
4、如何實(shí)現(xiàn)這個(gè)對(duì)象的引用計(jì)數(shù)呢?肯定不是由開(kāi)發(fā)人員來(lái)手動(dòng)地維護(hù)了,要開(kāi)發(fā)人員時(shí)刻記住什么時(shí)候該對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)加1,什么
時(shí)候該對(duì)這個(gè)對(duì)象的引用計(jì)數(shù)減1,一來(lái)是不方便開(kāi)發(fā),二來(lái)是不可靠,一不小心哪里多加了一個(gè)1或者多減了一個(gè)1,就會(huì)造成災(zāi)難性的后果。
5、智能指針是一個(gè)對(duì)象,不過(guò)這個(gè)對(duì)象代表的是另外一個(gè)真實(shí)使用的對(duì)象,當(dāng)智能指針指向?qū)嶋H對(duì)象的時(shí)候,就是智能指針對(duì)象創(chuàng)建的時(shí)候,當(dāng)智能指針不再指向?qū)嶋H對(duì)象的時(shí)候,就是智能指針對(duì)象銷(xiāo)毀的時(shí)候。在C++中,對(duì)象的創(chuàng)建和銷(xiāo)毀時(shí)會(huì)分別自動(dòng)地調(diào)用對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù),負(fù)責(zé)對(duì)真實(shí)對(duì)象的引用計(jì)數(shù)加1和減1的工作就落實(shí)到智能指針對(duì)象的構(gòu)造函數(shù)和析構(gòu)函數(shù)的身上了,這也是為什么稱這個(gè)指針對(duì)象為智能指針的原因。