51.JNI和NDK
? ? JNI是Java調(diào)用Native 語言的一種特性,屬于Java践叠,Java本地接口愚争,使Java與本地其他類型語言交互(C++)
? ? ? 實(shí)現(xiàn)步驟:在Java中聲明Native方法,編譯該文件得到.class文件饿幅,通過javah命令導(dǎo)出JNI頭文件(.h文件)险领,使用Java需要交互的本地代碼實(shí)現(xiàn)子啊Java中聲明的Native方法侨舆,編譯so文件,通過Java執(zhí)行Java程序绢陌,最終實(shí)現(xiàn)Java調(diào)用本地代碼
? ? NDK(Native Develop Kit):Android開發(fā)工具包挨下,屬于Android。
? ? 作用:快速開發(fā)C脐湾、C++動(dòng)態(tài)庫臭笆,并自動(dòng)將so文件和應(yīng)用打包成APK,即可通過NDK在Android中使用JNI與本地代碼(C沥割、C++)交互(Android開發(fā)需要本地代碼C耗啦、C++實(shí)現(xiàn))
? ? ? 特點(diǎn):運(yùn)行效率高凿菩,代碼安全性高机杜,功能拓展性好,易于代碼復(fù)用和移植衅谷。
? ? ? 使用步驟:①配置NDK環(huán)境椒拗;②創(chuàng)建Android項(xiàng)目,并于NDK進(jìn)行關(guān)聯(lián);③在Android項(xiàng)目中聲明所需調(diào)用的Native方法蚀苛;④使用該Native方法在验;⑤通過NDK build命令編譯產(chǎn)生so文件;⑥編譯AS工程堵未,實(shí)現(xiàn)調(diào)用本地代碼腋舌。
? ? JNI和NDK的關(guān)系:JNI實(shí)現(xiàn)目的,NDK是Android實(shí)現(xiàn)JNI的手段渗蟹,即在AS開發(fā)環(huán)境中通過NDK從而實(shí)現(xiàn)JNI功能块饺。
52.常用的設(shè)計(jì)模式及其實(shí)現(xiàn)思想和作用
轉(zhuǎn)載文章:23種設(shè)計(jì)模式全解析 - codeTao - 博客園
①單例模式:單例對(duì)象能保證在一個(gè)JVM中,該對(duì)象只有一個(gè)實(shí)例存在雌芽。
②工廠模式
一個(gè)抽象產(chǎn)品類授艰,可以派生出多個(gè)具體產(chǎn)品類。?一個(gè)抽象工廠類世落,可以派生出多個(gè)具體工廠類淮腾。每個(gè)具體工廠類只能創(chuàng)建一個(gè)具體產(chǎn)品類的實(shí)例。
抽象工廠模式:多個(gè)抽象產(chǎn)品類屉佳,每個(gè)抽象產(chǎn)品類可以派生出多個(gè)具體產(chǎn)品類谷朝。?一個(gè)抽象工廠類,可以派生出多個(gè)具體工廠類武花。?每個(gè)具體工廠類可以創(chuàng)建多個(gè)具體產(chǎn)品類的實(shí)例徘禁,也就是創(chuàng)建的是一個(gè)產(chǎn)品線下的多個(gè)產(chǎn)品。?
③適配器模式
將某個(gè)類的接口轉(zhuǎn)換成客戶端期望的另一個(gè)接口表示髓堪,目的是消除由于接口不匹配所造成的類的兼容性問題送朱。主要分為三類:類的適配器模式、對(duì)象的適配器模式干旁、接口的適配器模式驶沼。
④裝飾模式(Decorator)
顧名思義,裝飾模式就是給一個(gè)對(duì)象增加一些新的功能争群,而且是動(dòng)態(tài)的回怜,要求裝飾對(duì)象和被裝飾對(duì)象實(shí)現(xiàn)同一個(gè)接口,裝飾對(duì)象持有被裝飾對(duì)象的實(shí)例换薄。
Source類是被裝飾類玉雾,Decorator類是一個(gè)裝飾類,可以為Source類動(dòng)態(tài)的添加一些功能轻要。
裝飾器模式的應(yīng)用場景:
1复旬、需要擴(kuò)展一個(gè)類的功能。
2冲泥、動(dòng)態(tài)的為一個(gè)對(duì)象增加功能驹碍,而且還能動(dòng)態(tài)撤銷壁涎。(繼承不能做到這一點(diǎn),繼承的功能是靜態(tài)的志秃,不能動(dòng)態(tài)增刪怔球。)
缺點(diǎn):產(chǎn)生過多相似的對(duì)象,不易排錯(cuò)浮还!
⑤代理模式(Proxy):多一個(gè)代理類出來竟坛,替原對(duì)象進(jìn)行一些操作。
⑥橋接模式(Bridge):橋接模式就是把事物和其具體實(shí)現(xiàn)分開钧舌,使他們可以各自獨(dú)立的變化流码。橋接的用意是:將抽象化與實(shí)現(xiàn)化解耦,使得二者可以獨(dú)立變化延刘。
⑦觀察者模式:一個(gè)目標(biāo)物件管理所有相依于它的觀察者物件漫试,并且在它本身的狀態(tài)改變時(shí)主動(dòng)發(fā)出通知。這通常透過呼叫各觀察者所提供的方法來實(shí)現(xiàn)碘赖。此種模式通常被用來實(shí)現(xiàn)事件處理系統(tǒng)驾荣。
⑧訪問者模式:一種分離對(duì)象數(shù)據(jù)結(jié)構(gòu)與行為的方法,通過這種分離普泡,可達(dá)到為一個(gè)被訪問者動(dòng)態(tài)添加新的操作而無需做其它的修改的效果播掷。
53.HashMap、 HashTable撼班、HashSet的異同
轉(zhuǎn)載文章:HashSet HashTable HashMap的區(qū)別 及其Java集合介紹 - ywl925 - 博客園
①HashSet是Set的一個(gè)實(shí)現(xiàn)類歧匈,HashMap是Map的一個(gè)實(shí)現(xiàn)類,同時(shí)HashMap是HashTable的替代品
②HashSet以對(duì)象作為元素砰嘁,而HashMap以(key-value)的一組對(duì)象作為元素件炉,且HashSet拒絕接受重復(fù)的對(duì)象。HashMap可以看作三個(gè)視圖:key的Set矮湘,value的Collection斟冕,Entry的Set。 這里HashSet就是其實(shí)就是HashMap的一個(gè)視圖缅阳。
HashSet內(nèi)部就是使用HashMap實(shí)現(xiàn)的磕蛇,和HashMap不同的是它不需要Key和Value兩個(gè)值。
HashMap是一個(gè)數(shù)組和鏈表的結(jié)合體十办,新加入的放在鏈頭秀撇,重復(fù)的key不同的alue被新value替代
③繼承不同
public class Hashtable extends Dictionary<> implements Map<>
public class HashMap? extends AbstractMap<> implements Map<>
④HashTable 方法同步,而HashMap需要自己增加同步處理向族。
⑤HashTable中呵燕,key和value都不允許出現(xiàn)null值。
在HashMap中炸枣,null可以作為鍵虏等,這樣的鍵只有一個(gè)弄唧;可以有一個(gè)或多個(gè)鍵所對(duì)應(yīng)的值為null适肠。用containsKey()方法來判斷是否存在某個(gè)鍵霍衫。
⑥兩個(gè)遍歷方式的內(nèi)部實(shí)現(xiàn)上不同。
HashTable侯养、HashMap都使用了 Iterator敦跌。而由于歷史原因,HashTable還使用了Enumeration的方式 逛揩。
⑦哈希值的使用不同
HashTable直接使用對(duì)象的hashCode柠傍,HashTable中hash數(shù)組默認(rèn)大小是11,增加的方式是?old*2+1辩稽。
而HashMap重新計(jì)算hash值惧笛,HashMap中hash數(shù)組的默認(rèn)大小是16,而且一定是2的指數(shù)逞泄。
如何實(shí)現(xiàn)HashMap線程同步患整?
①使用 java.util.Hashtable 類,此類是線程安全的喷众。
②使用 java.util.concurrent.ConcurrentHashMap各谚,此類是線程安全的。
③使用 java.util.Collections.synchronizedMap() 方法包裝 HashMap object到千,得到線程安全的Map昌渤,并在此Map上進(jìn)行操作。
54.Android 中內(nèi)存泄漏原因及優(yōu)化方案憔四?
文章轉(zhuǎn)載:Android 中內(nèi)存泄漏的原因和解決方案 - 簡書
①非靜態(tài)內(nèi)部類造成的內(nèi)存泄漏 ?非靜態(tài)類會(huì)持有外部類的引用膀息,如果這個(gè)內(nèi)部類比外部類的生命周期長,在外部類被銷毀時(shí)了赵,內(nèi)部類無法回收履婉,即造成內(nèi)存泄漏;
②外部類中持有非靜態(tài)內(nèi)部類的靜態(tài)對(duì)象 ?保持一致的生命周期斟览,將內(nèi)部類對(duì)象改成非靜態(tài)毁腿;
③Handler 或 Runnable 作為非靜態(tài)內(nèi)部類 ?Handler 和 Runnable 作為匿名內(nèi)部類,都會(huì)持有 Activity 的引用苛茂,由于 Handler 和 Runnable 的生命周期比 Activity 長已烤,導(dǎo)致Activity 無法被回收,從而造成內(nèi)存泄漏妓羊。 ?解決辦法:將Handler 和 Runnable 定義為靜態(tài)內(nèi)部類胯究,在Activity 的onDestory()方法中調(diào)用Handler 的 removeCallbacks 方法來移除 Message。
還有一種特殊情況躁绸,如果 Handler 或者 Runnable 中持有 Context 對(duì)象裕循,那么即使使用靜態(tài)內(nèi)部類臣嚣,還是會(huì)發(fā)生內(nèi)存泄漏。解決辦法:使用弱引用
④其他內(nèi)存泄漏情況:比如BraodcastReceiver 未注銷剥哑,InputStream 未關(guān)閉硅则,再代碼中多注意注銷或關(guān)閉。
55.LeakCanary內(nèi)存優(yōu)化
參考文章:LeakCanary原理解析 - 簡書
①項(xiàng)目如何使用LeakCanary
LeakCanary.enableDisplayLeakActivity(context);內(nèi)存溢出圖標(biāo)株婴,圖標(biāo)以通知的形式顯示內(nèi)存溢出
②工作機(jī)制
LeakCanary.install()?會(huì)返回一個(gè)預(yù)定義的?RefWatcher怎虫,同時(shí)也會(huì)啟用一個(gè)?ActivityRefWatcher,用于自動(dòng)監(jiān)控調(diào)用Activity.onDestroy()?之后泄露的 activity困介。
1.RefWatcher.watch()?創(chuàng)建一個(gè)?KeyedWeakReference?到要被監(jiān)控的對(duì)象大审。
2.然后在后臺(tái)線程檢查引用是否被清除,如果沒有座哩,調(diào)用GC徒扶。
3.如果引用還是未被清除,把 heap 內(nèi)存 dump 到 APP 對(duì)應(yīng)的文件系統(tǒng)中的一個(gè)?.hprof?文件中根穷。
4.在另外一個(gè)進(jìn)程中的?HeapAnalyzerService?有一個(gè)?HeapAnalyzer?使用HAHA?解析這個(gè)文件姜骡。
5.得益于唯一的 reference key,?HeapAnalyzer?找到?KeyedWeakReference,定位內(nèi)存泄露缠诅。
6.HeapAnalyzer?計(jì)算?到 GC roots 的最短強(qiáng)引用路徑溶浴,并確定是否是泄露。如果是的話管引,建立導(dǎo)致泄露的引用鏈士败。
7.引用鏈傳遞到 APP 進(jìn)程中的?DisplayLeakService, 并以通知的形式展示出來褥伴。
56.多線程谅将、線程池
參考文章:Java中的多線程你只要看這一篇就夠了 - Givefine - 博客園
線程的并行和并發(fā)
并行:多個(gè)cpu實(shí)例或者多臺(tái)機(jī)器同時(shí)執(zhí)行一段處理邏輯,是真正的同時(shí)重慢。
并發(fā):通過cpu調(diào)度算法饥臂,讓用戶看上去同時(shí)執(zhí)行,實(shí)際上從cpu操作層面不是真正的同時(shí)似踱。并發(fā)往往在場景中有公用的資源隅熙,那么針對(duì)這個(gè)公用的資源往往產(chǎn)生瓶頸,我們會(huì)用TPS或者QPS來反應(yīng)這個(gè)系統(tǒng)的處理能力核芽。
線程安全:多個(gè)線程訪問同一個(gè)對(duì)象時(shí)囚戚,如果不用考慮這些線程在運(yùn)行時(shí)環(huán)境下的調(diào)度和交替執(zhí)行,也不需要進(jìn)行額外的同步轧简,或者在調(diào)用方進(jìn)行任何其他操作驰坊,調(diào)用這個(gè)對(duì)象的行為都可以獲得正確的結(jié)果,那么這個(gè)對(duì)象就是線程安全的哮独。
線程同步:即當(dāng)有一個(gè)線程在對(duì)內(nèi)存進(jìn)行操作時(shí)拳芙,其他線程都不可以對(duì)這個(gè)內(nèi)存地址進(jìn)行操作察藐,直到該線程完成操作, 其他線程才能對(duì)該內(nèi)存地址進(jìn)行操作舟扎,而其他線程又處于等待狀態(tài)分飞,實(shí)現(xiàn)線程同步的方法有很多,臨界區(qū)對(duì)象就是其中一種浆竭。
Java通過Executors提供四種線程池(from 百度)
newCachedThreadPool——?jiǎng)?chuàng)建一個(gè)可緩存線程池浸须,如果線程池長度超過處理需要惨寿,可靈活回收空閑線程邦泄,若無可回收,則新建線程裂垦。
newFixedThreadPool——?jiǎng)?chuàng)建一個(gè)定長線程池顺囊,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待蕉拢。
newScheduledThreadPool——?jiǎng)?chuàng)建一個(gè)定長線程池特碳,支持定時(shí)及周期性任務(wù)執(zhí)行。
newSingleThreadExecutor——?jiǎng)?chuàng)建一個(gè)單線程化的線程池晕换,它只會(huì)用唯一的工作線程來執(zhí)行任務(wù)午乓,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行。
參考文章:Java并發(fā)編程:線程池的使用 - Matrix海子 - 博客園
①線程池中的線程初始化
創(chuàng)建線程池后闸准,線程池中沒有線程益愈,需要提交任務(wù)才會(huì)創(chuàng)建線程。
prestartCoreThread():初始化一個(gè)核心線程夷家;
prestartAllCoreThreads():初始化所有核心線程
②workQueue蒸其,任務(wù)緩存隊(duì)列,用來存放等待執(zhí)行的任務(wù)
workQueue的類型為BlockingQueue<Runnable>库快,通趁可以取下面三種類型:
1)ArrayBlockingQueue:基于數(shù)組的先進(jìn)先出隊(duì)列,此隊(duì)列創(chuàng)建時(shí)必須指定大幸迤痢靠汁;
2)LinkedBlockingQueue:基于鏈表的先進(jìn)先出隊(duì)列,如果創(chuàng)建時(shí)沒有指定此隊(duì)列大小闽铐,則默認(rèn)為Integer.MAX_VALUE蝶怔;
3)SynchronousQueue:這個(gè)隊(duì)列比較特殊,它不會(huì)保存提交的任務(wù)阳啥,而是將直接新建一個(gè)線程來執(zhí)行新來的任務(wù)添谊。
③任務(wù)拒絕策略
當(dāng)線程池的任務(wù)緩存隊(duì)列已滿或線程數(shù)目達(dá)到maximumPoolSize,還有任務(wù)來時(shí)會(huì)采用任務(wù)拒絕策略
1)ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常察迟。
2)ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù)斩狱,但是不拋出異常耳高。
3)ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
4)ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)
④線程池的關(guān)閉
1)shutdown():不會(huì)立即終止線程池所踊,而是要等所有任務(wù)緩存隊(duì)列中的任務(wù)都執(zhí)行完后才終止泌枪,但再也不會(huì)接受新的任務(wù)
2)shutdownNow():立即終止線程池,并嘗試打斷正在執(zhí)行的任務(wù)秕岛,并且清空任務(wù)緩存隊(duì)列碌燕,返回尚未執(zhí)行的任務(wù)
⑤線程池容量的動(dòng)態(tài)調(diào)整
1)setCorePoolSize:設(shè)置核心池大小
2)setMaximumPoolSize:設(shè)置線程池最大能創(chuàng)建的線程數(shù)目大小
參考文章:由淺入深理解Java線程池及線程池的如何使用 - Janti - 博客園
corePoolSize?:線程池的核心池大小,在創(chuàng)建線程池之后继薛,線程池默認(rèn)沒有任何線程修壕。
當(dāng)有任務(wù)過來的時(shí)候才會(huì)去創(chuàng)建創(chuàng)建線程執(zhí)行任務(wù)。換個(gè)說法遏考,線程池創(chuàng)建之后慈鸠,線程池中的線程數(shù)為0,當(dāng)任務(wù)過來就會(huì)創(chuàng)建一個(gè)線程去執(zhí)行灌具,直到線程數(shù)達(dá)到corePoolSize之后青团,就會(huì)被到達(dá)的任務(wù)放在隊(duì)列中。(注意是到達(dá)的任務(wù))咖楣。換句更精煉的話:corePoolSize表示允許線程池中允許同時(shí)運(yùn)行的最大線程數(shù)督笆。
如果執(zhí)行了線程池的prestartAllCoreThreads()方法,線程池會(huì)提前創(chuàng)建并啟動(dòng)所有核心線程诱贿。
maximumPoolSize?:線程池允許的最大線程數(shù)娃肿,他表示最大能創(chuàng)建多少個(gè)線程。maximumPoolSize肯定是大于等于corePoolSize瘪松。
keepAliveTime?:表示線程沒有任務(wù)時(shí)最多保持多久然后停止咸作。默認(rèn)情況下,只有線程池中線程數(shù)大于corePoolSize時(shí)宵睦,keepAliveTime才會(huì)起作用记罚。換句話說,當(dāng)線程池中的線程數(shù)大于corePoolSize壳嚎,并且一個(gè)線程空閑時(shí)間達(dá)到了keepAliveTime桐智,那么就是shutdown。
Unit:keepAliveTime的單位烟馅。
workQueue:一個(gè)阻塞隊(duì)列说庭,用來存儲(chǔ)等待執(zhí)行的任務(wù),當(dāng)線程池中的線程數(shù)超過它的corePoolSize的時(shí)候郑趁,線程會(huì)進(jìn)入阻塞隊(duì)列進(jìn)行阻塞等待刊驴。通過workQueue,線程池實(shí)現(xiàn)了阻塞功能
threadFactory:線程工廠,用來創(chuàng)建線程捆憎。
handler?:表示當(dāng)拒絕處理任務(wù)時(shí)的策略咧虎。
在java doc中亥宿,并不提倡我們直接使用ThreadPoolExecutor恋技,而是使用Executors類中提供的幾個(gè)靜態(tài)方法來創(chuàng)建線程池:
Executors.newCachedThreadPool();?//創(chuàng)建一個(gè)緩沖池智袭,緩沖池容量大小為Integer.MAX_VALUE
Executors.newSingleThreadExecutor();?//創(chuàng)建容量為1的緩沖池
Executors.newFixedThreadPool(int);?//創(chuàng)建固定容量大小的緩沖池
57.騰訊 Bugly
騰訊公司為移動(dòng)開發(fā)者開放的服務(wù)之一,面向移動(dòng)開發(fā)者提供專業(yè)的 Crash 監(jiān)控础拨、崩潰分析等質(zhì)量跟蹤服務(wù)氮块。Bugly 能幫助移動(dòng)互聯(lián)網(wǎng)開發(fā)者更及時(shí)地發(fā)現(xiàn)掌控異常,更全面的了解定位異常诡宗,更高效的修復(fù)解決異常滔蝉。
針對(duì)移動(dòng)應(yīng)用,騰訊 Bugly 提供了專業(yè)的 Crash僚焦、Android ANR ( application not response)锰提、iOS 卡頓監(jiān)控和解決方案曙痘。移動(dòng)開發(fā)者 ( Android / iOS ) 可以通過監(jiān)控芳悲,快速發(fā)現(xiàn)用戶在使用過程中出現(xiàn)的 Crash (崩潰)、Android ANR 和 iOS 卡頓边坤,并根據(jù)上報(bào)的信息快速定位和解決問題名扛。
58.Glide?
項(xiàng)目依賴Glide,在app build.gradle 中配置 compile'com.github.bumptech.glide:glide:3.7.0'
使用glide3.7版本茧痒,更高版本或出現(xiàn)異常:Error:Failed to resolve: com.android.support:support-annotations:27.0.2
Glide緩存機(jī)制
內(nèi)存存緩存的 讀存都在Engine類中完成肮韧。內(nèi)存緩存使用弱引用和LruCache結(jié)合完成的,弱引用來緩存的是正在使用中的圖片。圖片封裝類Resources內(nèi)部有個(gè)計(jì)數(shù)器判斷是該圖片否正在使用旺订。
Glide內(nèi)存緩存的流程
讀:是先從lruCache取弄企,取不到再從弱引用中取区拳;
存:內(nèi)存緩存取不到拘领,從網(wǎng)絡(luò)拉取回來先放在弱引用里,渲染圖片樱调,圖片對(duì)象Resources使用計(jì)數(shù)加一约素;
渲染完圖片,圖片對(duì)象Resources使用計(jì)數(shù)減一笆凌,如果計(jì)數(shù)為0圣猎,圖片緩存從弱引用中刪除,放入lruCache緩存乞而。
參考文章:
Glide 系列(四) Glide緩存機(jī)制 - 野生的安卓獸 - 簡書
59.Fresco
項(xiàng)目依賴Glide送悔,在app build.gradle 中配置:implementation'com.facebook.fresco:fresco:1.9.0'
https://github.com/desmond1121/Fresco-Source-Analysis
https://blog.csdn.net/yw59792649/article/details/78921025
60.React Native
混合開發(fā)技術(shù)移動(dòng)開發(fā)-混合App介紹 - Primise7的博客 - CSDN博客
上一篇:Android基礎(chǔ)知識(shí)總結(jié)(五)