Android-收集-持續(xù)更新中...

1油挥、Activity相關(guān):

1敏释、Activity的生命周期

image

2癣疟、Activity的啟動(dòng)模式以及使用場(chǎng)景

啟動(dòng)模式

  1. standard:默認(rèn)的啟動(dòng)模式,每次創(chuàng)建都會(huì)產(chǎn)生新的實(shí)例惕虑,誰啟動(dòng)了該模式的Activity坟冲,該Activity就屬于啟動(dòng)它的Activity的任務(wù)棧中
  2. singleTop:棧頂復(fù)用模式,如果新的activity已經(jīng)位于棧頂溃蔫,那么這個(gè)Activity不會(huì)被重寫創(chuàng)建樱衷,同時(shí)它的onNewIntent(Intent intent)方法會(huì)被調(diào)用,通過此方法的參數(shù)我們可以去除當(dāng)前請(qǐng)求的信息酒唉,該 Activity的實(shí)例不在該椌毓穑或者不在棧頂 時(shí),其行為同standard啟動(dòng)模式
  3. singleTask:棧內(nèi)復(fù)用模式痪伦,如果棧中存在這個(gè)Activity的實(shí)例就會(huì)復(fù)用這個(gè)Activity侄榴,不管它是否位于棧頂,復(fù)用時(shí)网沾,會(huì)將它上面的Activity全部出棧癞蚕,并且會(huì)回調(diào)該實(shí)例的onNewIntent方法。
  4. singleInstance:全局唯一模式辉哥,具備singleTask模式的所有特性外桦山,與它的區(qū)別就是,這種模式下的Activity會(huì)單獨(dú)占用一個(gè)Task棧醋旦,具有全局唯一性恒水,即整個(gè)系統(tǒng)中就這么一個(gè)實(shí)例,由于棧內(nèi)復(fù)用的特性饲齐,后續(xù)的請(qǐng)求均不會(huì)創(chuàng)建新的Activity實(shí)例钉凌,除非這個(gè)特殊的任務(wù)棧被銷毀了,當(dāng)復(fù)用該實(shí)例 會(huì)回調(diào)onNewIntent方法

3捂人、Activity的啟動(dòng)過程(不要回答生命周期)

Activity 啟動(dòng)流程圖

Activity的啟動(dòng)過程
必須掌握的Activity啟動(dòng)過程

4御雕、在Activity中如何保存/恢復(fù)狀態(tài)矢沿?

分別調(diào)用onSaveInstanceState和onRestoreInstanceState 2個(gè)方法保存和恢復(fù)狀態(tài)。

5酸纲、在Activity中如何保存/恢復(fù)狀態(tài)捣鲸?

  • 不設(shè)置Activity的android:configChanges時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期闽坡,切橫屏?xí)r會(huì)執(zhí)行一次巍举,切豎屏?xí)r會(huì)執(zhí)行兩次裸卫;
  • 設(shè)置Activity的android:configChanges="orientation"時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫泽台、豎屏?xí)r只會(huì)執(zhí)行一次氮凝;
  • 設(shè)置Activity的android:configChanges="orientation|keyboardHidden"時(shí)们豌,切屏不會(huì)重新調(diào)用各個(gè)生命周期树碱,只會(huì)執(zhí)行onConfigurationChanged方法;

2次泽、Service相關(guān)

1穿仪、Service的兩種啟動(dòng)方式

1. Service的startService(Intent)啟動(dòng)方式
  • 使用這種start方式啟動(dòng)的Service的生命周期如下: onCreate()--->onStartCommand()(onStart()方法已過時(shí)) ---> onDestory()
  • 如果服務(wù)已經(jīng)開啟,不會(huì)重復(fù)的執(zhí)行onCreate()意荤, 而是會(huì)調(diào)用onStart()和onStartCommand()
  • 服務(wù)停止的時(shí)候調(diào)用 onDestory()啊片。服務(wù)只會(huì)被停止一次。
  • 特點(diǎn):一旦服務(wù)開啟跟調(diào)用者(開啟者)就沒有任何關(guān)系了玖像。
    開啟者退出了紫谷,開啟者掛了,服務(wù)還在后臺(tái)長(zhǎng)期的運(yùn)行捐寥。
    開啟者不能調(diào)用服務(wù)里面的方法笤昨。
2. 采用bind的方式開啟服務(wù)
  • 使用這種start方式啟動(dòng)的Service的生命周期如下:onCreate() --->onBind()--->onunbind()--->onDestory()
  • bind的方式開啟服務(wù),綁定服務(wù)握恳,調(diào)用者掛了瞒窒,服務(wù)也會(huì)跟著掛掉。
    綁定者可以調(diào)用服務(wù)里面的方法

3乡洼、Broadcast相關(guān)

1崇裁、Broadcast注冊(cè)方式與區(qū)別

  1. Manifest.xml中靜態(tài)注冊(cè):
//new出上邊定義好的BroadcastReceiver
MyBroadCastReceiver yBroadCastReceiver = new MyBroadCastReceiver();

//實(shí)例化過濾器并設(shè)置要過濾的廣播  
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");

//注冊(cè)廣播   
myContext.registerReceiver(smsBroadCastReceiver,intentFilter, 
             "android.permission.RECEIVE_SMS", null);

  1. 代碼中動(dòng)態(tài)注冊(cè):

直接在Manifest.xml文件的<application>節(jié)點(diǎn)中配置廣播接收者

<receiver android:name=".MyBroadCastReceiver">  
            <!-- android:priority屬性是設(shè)置此接收者的優(yōu)先級(jí)(從-1000到1000) -->
            <intent-filter android:priority="20">
            <actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>  
            </intent-filter>  
</receiver>


2、兩種注冊(cè)廣播的不同

  • 第一種不是常駐型廣播束昵,也就是說廣播跟隨程序的生命周期拔稳。
  • 第二種是常駐型,也就是說當(dāng)應(yīng)用程序關(guān)閉后妻怎,如果有信息廣播來壳炎,程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行。

3逼侦、發(fā)送廣播的兩種方式

  • 無序廣播:所有的接收者都會(huì)接收事件匿辩,不可以被攔截,不可以被修改榛丢。
  • 有序廣播:按照優(yōu)先級(jí)铲球,一級(jí)一級(jí)的向下傳遞,接收者可以修改廣播數(shù)據(jù)晰赞,也可以終止廣播事件稼病。

Android 兩種注冊(cè)、發(fā)送廣播的區(qū)別


補(bǔ)1掖鱼、ContentProvider相關(guān):

ContentProvider的基本使用方法和作用然走。ContentValue的使用方法,他和HashMap的區(qū)別是什么戏挡?

ContentProvider 是Android系統(tǒng)中提供的專門用戶不同應(yīng)用間進(jìn)行數(shù)據(jù)共享的組件芍瑞,提供了一套標(biāo)準(zhǔn)的接口用來獲取以及操作數(shù)據(jù),準(zhǔn)許開發(fā)者把自己的應(yīng)用數(shù)據(jù)根據(jù)需求開放給其他應(yīng)用進(jìn)行增刪改查褐墅,而無須擔(dān)心直接開放數(shù)據(jù)庫權(quán)限而帶來的安全問題拆檬。

ContentValue: 存儲(chǔ)數(shù)據(jù)封裝的HashMap,提供 put、get等方法

Android ContentProvider基本用法

4妥凳、網(wǎng)絡(luò)相關(guān)

1竟贯、HttpClient與HttpUrlConnection的區(qū)別 2

  1. 功能上:
  • Http Client:適用于web瀏覽器,擁有大量靈活的API逝钥,提供了很多工具屑那,封裝了http的請(qǐng)求頭,參數(shù)艘款,內(nèi)容體齐莲,響應(yīng),還有一些高級(jí)功能磷箕,代理选酗、COOKIE、鑒權(quán)岳枷、壓縮芒填、連接池的處理正因此,在不破壞兼容性的前提下空繁,其龐大的API也使人難以改進(jìn)殿衰。
  • HttpURLConnection: 對(duì)于大部分功能都進(jìn)行了包裝,Http Client的高級(jí)功能代碼會(huì)較復(fù)雜盛泡,

2.性能上:

  • HttpURLConnection直接支持GZIP壓縮闷祥,默認(rèn)添加"Accept-Encoding: gzip"頭字段到請(qǐng)求中,并處理相應(yīng)的回應(yīng),
  • 而Http Client雖然支持凯砍,但需要自己寫代碼處理箱硕。

3.選用:

  • Volley里用的哪種請(qǐng)求方式(2.3前HttpClient,2.3后HttpUrlConnection)

2悟衩、HTTPS和HTTP的區(qū)別 2

1剧罩、什么是 HTTPS

HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標(biāo)的HTTP通道座泳,簡(jiǎn)單講是HTTP的安全版惠昔。

即HTTP下加入SSL (Secure Socket Layer)層,HTTPS的安全基礎(chǔ)是SSL挑势,因此加密的詳細(xì)內(nèi)容就需要SSL镇防。


2、HTTPS 和 HTTP 的區(qū)別
  • https 用的 443 端口潮饱, http 用的 80 端口
  • https協(xié)議需要到ca申請(qǐng)證書来氧,一般免費(fèi)證書很少,需要交費(fèi)饼齿。
  • http是超文本傳輸協(xié)議饲漾,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協(xié)議缕溉。
  • http和https使用的是完全不同的連接方式考传,用的端口也不一樣,前者是80证鸥,后者是443僚楞。
  • http的連接很簡(jiǎn)單,是無狀態(tài)的枉层;HTTPS協(xié)議是由SSL+HTTP協(xié)議構(gòu)建的可進(jìn)行加密傳輸泉褐、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議,比http協(xié)議安全鸟蜡。

Android使用OkHttp請(qǐng)求自簽名的https網(wǎng)站
Android Https相關(guān)完全解析 當(dāng)OkHttp遇到Https
HTTPS和HTTP的區(qū)別


5膜赃、View相關(guān)

1、view的Touch事件傳遞機(jī)制

1揉忘、和touch相關(guān)的三個(gè)方法
  1. public boolean dispatchTouchEvent(MotionEvent ev); //用來分派event
  2. public boolean onInterceptTouchEvent(MotionEvent ev); //用來攔截event
  3. public boolean onTouchEvent(MotionEvent ev); //用來處理event
方 法 解析
dispatchTouchEvent() 用來分派事件跳座。其中調(diào)用了onInterceptTouchEvent()和onTouchEvent(),一般不重寫該方法泣矛,返回true則表示該事件被消費(fèi)
onInterceptTouchEvent() 用來攔截事件疲眷。ViewGroup類中的源碼實(shí)現(xiàn)就是{return false;}表示不攔截該事件,事件將向下傳遞(傳遞給其子View)您朽;若手動(dòng)重寫該方法狂丝,使其返回true則表示攔截,事件將終止向下傳遞,事件由當(dāng)前ViewGroup類來處理几颜,就是調(diào)用該類的onTouchEvent()方法
onTouchEvent() 用來處理事件倍试。返回true則表示該View能處理該事件,事件將終止向上傳遞(傳遞給其父View)菠剩;返回false表示不能處理易猫,則把事件傳遞給其父View的onTouchEvent()方法來處

Android中的dispatchTouchEvent()耻煤、onInterceptTouchEvent()和onTouchEvent()


6具壮、動(dòng)畫相關(guān)

1、Android中有幾種動(dòng)畫哈蝇?

Android3.0之前有2種棺妓,3.0后有3種。
  • FrameAnimation(逐幀動(dòng)畫):將多張圖片組合起來進(jìn)行播放炮赦,類似于早期電影的工作原理怜跑,很多App的loading是采用這種方式。
  • TweenAnimation(補(bǔ)間動(dòng)畫):是對(duì)某個(gè)View進(jìn)行一系列的動(dòng)畫的操作吠勘,包括淡入淡出(AlphaAnimation)性芬,縮放(ScaleAnimation),平移(TranslateAnimation)剧防,旋轉(zhuǎn)(RotateAnimation)四種模式植锉。
  • PropertyAnimation(屬性動(dòng)畫):屬性動(dòng)畫不再僅僅是一種視覺效果了,而是一種不斷地對(duì)值進(jìn)行操作的機(jī)制峭拘,并將值賦到指定對(duì)象的指定屬性上俊庇,可以是任意對(duì)象的任意屬性。

注1:AnimationSet 繼承自Animation鸡挠,是上面四種的組合容器管理類辉饱,沒有自己特有的屬性,他的屬性繼承自Animation拣展,所以特別注意彭沼,當(dāng)我們對(duì)set標(biāo)簽使用Animation的屬性時(shí)會(huì)對(duì)該標(biāo)簽下的所有子控件都產(chǎn)生影響。

注2:補(bǔ)間動(dòng)畫執(zhí)行之后并未改變View的真實(shí)布局屬性值备埃。切記這一點(diǎn)姓惑,譬如我們?cè)贏ctivity中有一個(gè)Button在屏幕上方,我們?cè)O(shè)置了平移動(dòng)畫移動(dòng)到屏幕下方然后保持動(dòng)畫最后執(zhí)行狀態(tài)呆在屏幕下方瓜喇,這時(shí)如果點(diǎn)擊屏幕下方動(dòng)畫執(zhí)行之后的Button是沒有任何反應(yīng)的挺益,而點(diǎn)擊原來屏幕上方?jīng)]有Button的地方卻響應(yīng)的是點(diǎn)擊Button的事件。


2乘寒、屬性動(dòng)畫

  • ObjectAnimator:繼承自ValueAnimator望众,允許你指定要進(jìn)行動(dòng)畫的對(duì)象以及該對(duì)象的一個(gè)屬性。
  • 大多數(shù)的情況使用ObjectAnimator就足夠了,因?yàn)樗沟媚繕?biāo)對(duì)象動(dòng)畫值的處理過程變得足夠簡(jiǎn)單烂翰,不用像ValueAnimator那樣自己寫動(dòng)畫更新的邏輯
  • ObjectAnimator的動(dòng)畫原理是不停的調(diào)用setXXX方法更新屬性值夯缺,所有使用ObjectAnimator更新屬性時(shí)的前提是Object必須聲明有g(shù)etXXX和setXXX方法
ObjectAnimator mObjectAnimator= ObjectAnimator.ofInt(view, "customerDefineAnyThingName", 0,  1).setDuration(2000);
mObjectAnimator.addUpdateListener(new AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                //int value = animation.getAnimatedValue();  可以獲取當(dāng)前屬性值
                //view.postInvalidate();  可以主動(dòng)刷新
                //view.setXXX(value);
                //view.setXXX(value);
                //......可以批量修改屬性
            }
        });
ObjectAnimator.ofFloat(view, "rotationY", 0.0f, 360.0f).setDuration(1000).start();
  • PropertyValuesHolder:多屬性動(dòng)畫同時(shí)工作管理類甘耿。有時(shí)候我們需要同時(shí)修改多個(gè)屬性踊兜,那就可以用到此類
PropertyValuesHolder a1 = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);  
PropertyValuesHolder a2 = PropertyValuesHolder.ofFloat("translationY", 0, viewWidth);  
......
ObjectAnimator.ofPropertyValuesHolder(view, a1, a2, ......).setDuration(1000).start();
  • ValueAnimator:屬性動(dòng)畫中的時(shí)間驅(qū)動(dòng),管理著動(dòng)畫時(shí)間的開始佳恬、結(jié)束屬性值捏境,相應(yīng)時(shí)間屬性值計(jì)算方法等。包含所有計(jì)算動(dòng)畫值的核心函數(shù)以及每一個(gè)動(dòng)畫時(shí)間節(jié)點(diǎn)上的信息毁葱、一個(gè)動(dòng)畫是否重復(fù)垫言、是否監(jiān)聽更新事件等,并且還可以設(shè)置自定義的計(jì)算類型倾剿。
ValueAnimator animator = ValueAnimator.ofFloat(0, mContentHeight);  //定義動(dòng)畫
animator.setTarget(view);   //設(shè)置作用目標(biāo)
animator.setDuration(5000).start();
animator.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation){
        float value = (float) animation.getAnimatedValue();
        view.setXXX(value);  //必須通過這里設(shè)置屬性值才有效
        view.mXXX = value;  //不需要setXXX屬性方法
    }
});

特別注意:ValueAnimator只是動(dòng)畫計(jì)算管理驅(qū)動(dòng)筷频,設(shè)置了作用目標(biāo),但沒有設(shè)置屬性前痘,需要通過updateListener里設(shè)置屬性才會(huì)生效凛捏。

  • AnimationSet:動(dòng)畫集合,提供把多個(gè)動(dòng)畫組合成一個(gè)組合的機(jī)制芹缔,并可設(shè)置動(dòng)畫的時(shí)序關(guān)系坯癣,如同時(shí)播放、順序播放或延遲播放乖菱。具體使用方法比較簡(jiǎn)單坡锡,如下:

Android應(yīng)用開發(fā)之所有動(dòng)畫使用詳解

7、Android中跨進(jìn)程通訊

android系統(tǒng)中應(yīng)用程序之間不能共享內(nèi)存窒所。
因此鹉勒,在不同應(yīng)用程序之間交互數(shù)據(jù)(跨進(jìn)程通訊)就稍微麻煩一些

  • 1、訪問其他應(yīng)用程序的Activity
如調(diào)用系統(tǒng)通話應(yīng)用
Intent callIntent=new Intent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
startActivity(callIntent);
  • 2吵取、Content Provider

Content Provider提供了一種在多個(gè)應(yīng)用程序之間數(shù)據(jù)共享的方式(跨進(jìn)程共享數(shù)據(jù))禽额。應(yīng)用程序可以利用Content Provider完成下面的工作

  1. 查詢數(shù)據(jù)
  2. 修改數(shù)據(jù)
  3. 添加數(shù)據(jù)
  4. 刪除數(shù)據(jù)

雖然Content Provider也可以在同一個(gè)應(yīng)用程序中被訪問,但這么做并沒有什么意義皮官。Content Provider存在的目的向其他應(yīng)用程序共享數(shù)據(jù)和允許其他應(yīng)用程序?qū)?shù)據(jù)進(jìn)行增脯倒、刪、改操作捺氢。
Android系統(tǒng)本身提供了很多Content Provider藻丢,例如,音頻摄乒、視頻悠反、聯(lián)系人信息等等残黑。我們可以通過這些Content Provider獲得相關(guān)信息的列表。這些列表數(shù)據(jù)將以Cursor對(duì)象返回斋否。因此梨水,從Content Provider返回的數(shù)據(jù)是二維表的形式。

如訪問系統(tǒng)相冊(cè)
  • 3茵臭、廣播(Broadcast)
廣播是一種被動(dòng)跨進(jìn)程通訊的方式疫诽。當(dāng)某個(gè)程序向系統(tǒng)發(fā)送廣播時(shí),其他的應(yīng)用程序只能被動(dòng)地接收廣播數(shù)據(jù)旦委。這就象電臺(tái)進(jìn)行廣播一樣奇徒,聽眾只能被動(dòng)地收聽,而不能主動(dòng)與電臺(tái)進(jìn)行溝通社证。例如獲取手機(jī)電量信息
  • 4逼龟、AIDL服務(wù)

2评凝、AIDL理解

1追葡、定義:Android系統(tǒng)中的進(jìn)程之間不能共享內(nèi)存,因此奕短,需要提供一些機(jī)制在不同進(jìn)程之間進(jìn)行數(shù)據(jù)通信宜肉。
為了使其他的應(yīng)用程序也可以訪問本應(yīng)用程序提供的服務(wù),Android系統(tǒng)采用了遠(yuǎn)程過程調(diào)用(Remote Procedure Call翎碑,RPC)方式來實(shí)現(xiàn)谬返。與很多其他的基于RPC的解決方案一樣,Android使用一種接口定義語言(Interface Definition Language日杈,IDL)來公開服務(wù)的接口遣铝。我們知道4個(gè)Android應(yīng)用程序組件中的3個(gè)(Activity、BroadcastReceiver和ContentProvider)都可以進(jìn)行跨進(jìn)程訪問莉擒,另外一個(gè)Android應(yīng)用程序組件Service同樣可以酿炸。因此,可以將這種可以跨進(jìn)程訪問的服務(wù)稱為AIDL(Android Interface Definition Language)服務(wù)涨冀。


3填硕、Binder理解

1、什么是binder:

Binder是Android實(shí)現(xiàn) 跨進(jìn)程通訊(IPC)的方式,是一種虛擬的物理設(shè)備驅(qū)動(dòng)鹿鳖,實(shí)現(xiàn)了IBindler 接口扁眯。

2、知識(shí)概念
  1. 一個(gè)進(jìn)程空間分為 用戶空間 & 內(nèi)核空間(Kernel)翅帜,即把進(jìn)程內(nèi) 用戶 & 內(nèi)核 隔離開來

區(qū)別:

  1. 進(jìn)程間姻檀,用戶空間的數(shù)據(jù)不可共享,所以用戶空間 = 不可共享空間
  2. 進(jìn)程間涝滴,內(nèi)核空間的數(shù)據(jù)可共享绣版,所以內(nèi)核空間 = 可共享空間
  1. 進(jìn)程隔離:保證 安全性 & 獨(dú)立性周荐,一個(gè)進(jìn)程 不能直接操作或者訪問另一個(gè)進(jìn)程,即Android的進(jìn)程是相互獨(dú)立僵娃、隔離的
  2. 跨進(jìn)程通信( IPC ):隔離后概作,由于某些需求,進(jìn)程間 需要合作 / 交互
  3. 跨進(jìn)程間通信的原理
  • 先通過 進(jìn)程間 的內(nèi)核空間進(jìn)行 數(shù)據(jù)交互
  • 再通過 進(jìn)程內(nèi) 的用戶空間 & 內(nèi)核空間進(jìn)行 數(shù)據(jù)交互默怨,從而實(shí)現(xiàn) 進(jìn)程間的用戶空間 的數(shù)據(jù)交互


    image
  • 而Binder讯榕,就是充當(dāng) 連接 兩個(gè)進(jìn)程(內(nèi)核空間)的通道。
3匙睹、Binder 跨進(jìn)程通信機(jī)制 模型
  1. 模型原理:
image
4愚屁、優(yōu)點(diǎn)

對(duì)比 Linux (Android基于Linux)上的其他進(jìn)程通信方式(管道、消息隊(duì)列痕檬、共享內(nèi)存霎槐、
信號(hào)量、Socket)梦谜,Binder 機(jī)制的優(yōu)點(diǎn)有:


image

Binder學(xué)習(xí)指南

圖文詳解 Android Binder跨進(jìn)程通信的原理


8丘跌、Handler相關(guān)

1、handler 消息傳遞分析

作用:Handle 進(jìn)行消息傳遞

  1. Handle發(fā)送的msg通過enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)添加進(jìn)(MessageQueue)消息隊(duì)列中.

Android 消息傳遞機(jī)制分析


2唁桩、Handle闭树、Message、MessageQueue荒澡、Looper之間的關(guān)系

  • Handle:主要發(fā)送 Message
  • Message:消息
  • MessageQueue:消息隊(duì)列.保存由Looper發(fā)送的消息列表报辱。
  • Looper:用于為線程運(yùn)行消息循環(huán)的類。Thread默認(rèn)情況下沒有與之關(guān)聯(lián)单山,通過prepare()循環(huán)運(yùn)行在線程中碍现,通過loop(for(;;))來處理消息。

9米奸、熱修復(fù)相關(guān)

1昼接、熱修復(fù)包含:

  1. 資源替換
  2. 類替換(四大組件、類)
  3. SO補(bǔ)丁

2躏升、資源替換方法:

思路:Andorid APP默認(rèn)的類加載是PathClassLoader,這個(gè)只能加載自己APK的dex文件辩棒,所以我們需要使用DexClassLoader。我們用DexClassLoader加載外部的APK之后膨疏,通過反射獲取對(duì)應(yīng)的資源一睁。


3、類替換(四大組件佃却、類):

  1. 通過PathClassLoader 來加載我們自身App的dex
  2. 通過DexClassLoader來加載我們的補(bǔ)丁dex文件,這里面就是沒有bug的dex
  3. 反射兩個(gè)classLoader的<DexPathList pathList;>
  4. 接著我們來繼續(xù)反射兩個(gè)classloader中的pathList(注意:是兩個(gè)!一個(gè)是我們自己應(yīng)用的,另一個(gè)是我們補(bǔ)丁的,PathClassLoader和DexClassLoader都繼承BaseDexClassLoader),DexPathList里面的<Element[] dexElements;>,沒錯(cuò)還是拿到這個(gè)數(shù)組的值
  5. 合并兩個(gè)反射到的Element 數(shù)組!這里是重中之重.我們需要把我們的補(bǔ)丁dex放在數(shù)組的最前面!
  6. 將合并的新的數(shù)組,通過Field重新設(shè)置到我們自身App的DexPathList->dexElements.沒錯(cuò)!就是合并之后覆蓋有bug那個(gè)loader的Element 數(shù)組!!
  7. 通過Android build-tools 中的dx命令打包一個(gè)沒有bug的dex

Android 熱修復(fù)(全網(wǎng)最簡(jiǎn)單的熱修復(fù)講解)


4者吁、SO補(bǔ)丁:


10饲帅、圖片加載緩存相關(guān)

1复凳、設(shè)計(jì)一套圖片異步加載緩存方案

緩存層分為三層:內(nèi)存層瘤泪,磁盤層,網(wǎng)絡(luò)層

  • 內(nèi)存層:內(nèi)存緩存相對(duì)于磁盤緩存而言育八,速度要來的快很多对途,但缺點(diǎn)容量較小且會(huì)被系統(tǒng)回收,這里的實(shí)現(xiàn)我用到了LruCache髓棋。
  • 磁盤層:相比內(nèi)存緩存而言速度要來得慢很多实檀,但容量很大,這里的實(shí)現(xiàn)我用到了DiskLruCache類按声。
  • 網(wǎng)絡(luò)層:網(wǎng)絡(luò)訪問實(shí)現(xiàn)我用到了開源框架Volley

11膳犹、內(nèi)存泄露及管理

1、內(nèi)存泄漏:

  • 內(nèi)存泄露:程序在向系統(tǒng)申請(qǐng)分配內(nèi)存空間后(new)签则,在使用完畢后未釋放须床。結(jié)果導(dǎo)致一直占據(jù)該內(nèi)存單元,我們和程序都無法再使用該內(nèi)存單元渐裂,直到程序結(jié)束豺旬,這是內(nèi)存泄露。
  • 內(nèi)存溢出:程序向系統(tǒng)申請(qǐng)的內(nèi)存空間超出了系統(tǒng)能給的芯义。比如內(nèi)存只能分配一個(gè)int類型哈垢,我卻要塞給他一個(gè)long類型,系統(tǒng)就出現(xiàn)oom扛拨。又比如一車最多能坐5個(gè)人,你卻非要塞下10個(gè)举塔,車就擠爆了绑警。
  • 大量的內(nèi)存泄露會(huì)導(dǎo)致內(nèi)存溢出(oom)

2央渣、內(nèi)存:

  • 棧(stack):是簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)计盒,但在計(jì)算機(jī)中使用廣泛。棧最顯著的特征是:LIFO(Last In, First Out, 后進(jìn)先出)芽丹,棧中只存放基本類型和對(duì)象的引用(不是對(duì)象)北启。
  • 堆(heap):堆內(nèi)存用于存放由new創(chuàng)建的對(duì)象和數(shù)組。在堆中分配的內(nèi)存拔第,由java虛擬機(jī)自動(dòng)垃圾回收器來管理咕村。JVM只有一個(gè)堆區(qū)(heap)被所有線程共享,堆中不存放基本類型和對(duì)象引用蚊俺,只存放對(duì)象本身懈涛。
  • 方法區(qū)(method):又叫靜態(tài)區(qū),跟堆一樣泳猬,被所有的線程共享批钠。方法區(qū)包含所有的class和static變量宇植。

3、內(nèi)存優(yōu)化

  1. 單例導(dǎo)致內(nèi)存泄露
public class AppSettings {

    private static AppSettings sInstance;
    private Context mContext;

    private AppSettings(Context context) {
        this.mContext = context;
        
        //this.mContext = context.getApplicationContext();
    }

    public static AppSettings getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new AppSettings(context);
        }
        return sInstance;
    }
}

2埋心、靜態(tài)變量導(dǎo)致內(nèi)存泄露

public class MainActivity extends AppCompatActivity {

    private static Info sInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (sInfo != null) {
            sInfo = new Info(this);
        }
    }
}

class Info {
    public Info(Activity activity) {
    }
}

Info作為Activity的靜態(tài)成員指郁,并且持有Activity的引用,但是sInfo作為靜態(tài)變量拷呆,生命周期肯定比Activity長(zhǎng)坡氯。所以當(dāng)Activity退出后,sInfo仍然引用了Activity洋腮,Activity不能被回收箫柳,這就導(dǎo)致了內(nèi)存泄露。

3啥供、非靜態(tài)內(nèi)部類導(dǎo)致內(nèi)存泄露

非靜態(tài)內(nèi)部類(包括匿名內(nèi)部類)默認(rèn)就會(huì)持有外部類的引用悯恍,當(dāng)非靜態(tài)內(nèi)部類對(duì)象的生命周期比外部類對(duì)象的生命周期長(zhǎng)時(shí),就會(huì)導(dǎo)致內(nèi)存泄露伙狐。

public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        start();
    }

    private void start() {
        Message msg = Message.obtain();
        msg.what = 1;
        mHandler.sendMessage(msg);
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                // 做相應(yīng)邏輯
            }
        }
    };
}

熟悉Handler消息機(jī)制的都知道涮毫,mHandler會(huì)作為成員變量保存在發(fā)送的消息msg中,即msg持有mHandler的引用贷屎,而mHandler是Activity的非靜態(tài)內(nèi)部類實(shí)例罢防,即mHandler持有Activity的引用,那么我們就可以理解為msg間接持有Activity的引用唉侄。msg被發(fā)送后先放到消息隊(duì)列MessageQueue中咒吐,然后等待Looper的輪詢處理(MessageQueue和Looper都是與線程相關(guān)聯(lián)的,MessageQueue是Looper引用的成員變量属划,而Looper是保存在ThreadLocal中的)恬叹。那么當(dāng)Activity退出后,msg可能仍然存在于消息對(duì)列MessageQueue中未處理或者正在處理同眯,那么這樣就會(huì)導(dǎo)致Activity無法被回收绽昼,以致發(fā)生Activity的內(nèi)存泄露。

通常在Android開發(fā)中如果要使用內(nèi)部類须蜗,但又要規(guī)避內(nèi)存泄露硅确,一般都會(huì)采用靜態(tài)內(nèi)部類+弱引用的方式。

public class MainActivity extends AppCompatActivity {

    private Handler mHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mHandler = new MyHandler(this);
        start();
    }

    private void start() {
        Message msg = Message.obtain();
        msg.what = 1;
        mHandler.sendMessage(msg);
    }

    private static class MyHandler extends Handler {

        private WeakReference<MainActivity> activityWeakReference;

        public MyHandler(MainActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = activityWeakReference.get();
            if (activity != null) {
                if (msg.what == 1) {
                    // 做相應(yīng)邏輯
                }
            }
        }
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacksAndMessages(null);
}

非靜態(tài)內(nèi)部類造成內(nèi)存泄露還有一種情況就是使用Thread或者AsyncTask

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 模擬相應(yīng)耗時(shí)邏輯
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}


這種方式新建的子線程Thread和AsyncTask都是匿名內(nèi)部類對(duì)象明肮,默認(rèn)就隱式的持有外部Activity的引用菱农,導(dǎo)致Activity內(nèi)存泄露。

4晤愧、未取消注冊(cè)或回調(diào)導(dǎo)致內(nèi)存泄露

  • 在Activity中注冊(cè)廣播大莫,如果在Activity銷毀后不取消注冊(cè)

5、Timer和TimerTask導(dǎo)致內(nèi)存泄露

  • Timer和TimerTask在Android中通常會(huì)被用來做一些計(jì)時(shí)或循環(huán)任務(wù)

6官份、集合中的對(duì)象未清理造成內(nèi)存泄露

如果一個(gè)對(duì)象放入到ArrayList只厘、HashMap等集合中烙丛,這個(gè)集合就會(huì)持有該對(duì)象的引用。當(dāng)我們不再需要這個(gè)對(duì)象時(shí)羔味,也并沒有將它從集合中移除河咽,這樣只要集合還在使用(而此對(duì)象已經(jīng)無用了),這個(gè)對(duì)象就造成了內(nèi)存泄露赋元。并且如果集合被靜態(tài)引用的話忘蟹,集合里面那些沒有用的對(duì)象更會(huì)造成內(nèi)存泄露了。所以在使用集合時(shí)要及時(shí)將不用的對(duì)象從集合remove搁凸,或者clear集合媚值,以避免內(nèi)存泄漏。

7护糖、資源未關(guān)閉或釋放導(dǎo)致內(nèi)存泄露

在使用IO褥芒、File流或者Sqlite、Cursor等資源時(shí)要及時(shí)關(guān)閉嫡良。這些資源在進(jìn)行讀寫操作時(shí)通常都使用了緩沖锰扶,如果及時(shí)不關(guān)閉,這些緩沖對(duì)象就會(huì)一直被占用而得不到釋放寝受,以致發(fā)生內(nèi)存泄露坷牛。因此我們?cè)诓恍枰褂盟鼈兊臅r(shí)候就及時(shí)關(guān)閉,以便緩沖能及時(shí)得到釋放很澄,從而避免內(nèi)存泄露京闰。

8、屬性動(dòng)畫造成內(nèi)存泄露

動(dòng)畫同樣是一個(gè)耗時(shí)任務(wù)痴怨,比如在Activity中啟動(dòng)了屬性動(dòng)畫(ObjectAnimator)忙干,但是在銷毀的時(shí)候,沒有調(diào)用cancle方法浪藻,雖然我們看不到動(dòng)畫了,但是這個(gè)動(dòng)畫依然會(huì)不斷地播放下去乾翔,動(dòng)畫引用所在的控件爱葵,所在的控件引用Activity,這就造成Activity無法正常釋放反浓。因此同樣要在Activity銷毀的時(shí)候cancel掉屬性動(dòng)畫萌丈,避免發(fā)生內(nèi)存泄漏。

@Override
protected void onDestroy() {
    super.onDestroy();
    mAnimator.cancel();
}

9雷则、WebView造成內(nèi)存泄露

關(guān)于WebView的內(nèi)存泄露辆雾,因?yàn)閃ebView在加載網(wǎng)頁后會(huì)長(zhǎng)期占用內(nèi)存而不能被釋放,因此我們?cè)贏ctivity銷毀后要調(diào)用它的destory()方法來銷毀它以釋放內(nèi)存月劈。

@Override
protected void onDestroy() {
    super.onDestroy();
    // 先從父控件中移除WebView
    mWebViewContainer.removeView(mWebView);
    mWebView.stopLoading();
    mWebView.getSettings().setJavaScriptEnabled(false);
    mWebView.clearHistory();
    mWebView.removeAllViews();
    mWebView.destroy();
}

10度迂、總結(jié)

1).資源對(duì)象沒關(guān)閉造成的內(nèi)存泄漏
2).構(gòu)造Adapter時(shí)藤乙,沒有使用緩存的convertView
3).Bitmap對(duì)象不在使用時(shí)調(diào)用recycle()釋放內(nèi)存
4).試著使用關(guān)于application的context來替代和activity相關(guān)的context
5).注冊(cè)沒取消造成的內(nèi)存泄漏
6).集合中對(duì)象沒清理造成的內(nèi)存泄漏

查找內(nèi)存泄漏可以使用Android Stdio 自帶的Android Profiler工具,也可以使用Square產(chǎn)品的LeadCanary.

12、android 屏幕適配

  • 在 XML 布局文件中指定尺寸時(shí)使用 wrap_content惭墓、match_parent 或 dp 單位 坛梁。
  • 不要在應(yīng)用代碼中使用硬編碼的像素值
  • 不要使用 AbsoluteLayout(已棄用)
  • 為不同屏幕密度提供替代位圖可繪制對(duì)象
image

支持多種屏幕

面向多種屏幕的設(shè)計(jì)

Android 屏幕適配:最全面的解決方案

13、HybridJAVA 與JS交互

  • Android 調(diào) JS :
    1腊凶、java
webView.loadUrl("javascript:javacalljs()");

??2划咐、Html


image

注意:考慮有返回值情況;Android在4.4之前并沒有提供直接調(diào)用js函數(shù)并獲取值的方法钧萍,所以在此之前褐缠,常用的思路是 java調(diào)用js方法,js方法執(zhí)行完畢风瘦,再次調(diào)用java代碼將值返回队魏。

// 4.4之后 java代碼時(shí)用evaluateJavascript方法調(diào)用
private void testEvaluateJavascript(WebView webView) {
  webView.evaluateJavascript("getGreetings()", new ValueCallback<String>() {

  @Override
  public void onReceiveValue(String value) {
      Log.i(LOGTAG, "onReceiveValue value=" + value);
  }});
}
  • JS 調(diào) Android :
    1、java
webView.addJavascriptInterface(MainActivity.this,"android");

??2弛秋、html

<body>
HTML 內(nèi)容顯示 <br/>
<h1><div id="content">內(nèi)容顯示</div></h1><br/>
<input type="button"  value="點(diǎn)擊調(diào)用java代碼" onclick="window.android.startFunction()" /><br/>
<input type="button"  value="點(diǎn)擊調(diào)用java代碼并傳遞參數(shù)" onclick="window.android.startFunction('http://blog.csdn.net/Leejizhou')"  />
</body>

Android中Java和JavaScript交互

14器躏、單例模式(手寫)

//懶漢式
public class Singleton {
    private static Singleton singleton;

    private Singleton() {

    }

    public static synchronized Singleton getSingleton() {
        if (singleton == null) {
            singleton = new Singleton();
        }

        return singleton;
    }
}

//餓漢式
public class Singleton {
    private static final Singleton singleton = new Singleton();

    private Singleton () {

    }

    public static Singleton getSingleton() {
        return singleton;
    }
}
//double-lock
public class Singleton {
    private volatile static Singleton singleton;

    private Singleton() {

    }

    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized(Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }

        return singleton;
    }
}

14、ANR相關(guān)

1蟹略、什么是ANR

在Android上登失,如果你的應(yīng)用程序有一段時(shí)間響應(yīng)不夠靈敏,系統(tǒng)會(huì)向用戶顯示一個(gè)對(duì)話框挖炬,這個(gè)對(duì)話框稱作應(yīng)用程序無響應(yīng)(ANR:Application Not Responding)對(duì)話框揽浙。


2、ANR產(chǎn)生的原因

ANR產(chǎn)生的根本原因是APP阻塞了UI線程


3意敛、ANR產(chǎn)生的原因

1:UI線程盡量只做跟UI相關(guān)的工作馅巷,但一些復(fù)雜的UI操作,還是需要一些技巧來處理草姻,不如你讓一個(gè)Button去setText一個(gè)10M的文本钓猬,UI肯定崩掉了,不過對(duì)于此類問題撩独,分段加載貌似是最好的方法了敞曹。
2:讓耗時(shí)的工作(比如數(shù)據(jù)庫操作,I/O综膀,連接網(wǎng)絡(luò)或者別的有可能阻礙UI線程的操作)把它放入單獨(dú)的線程處理澳迫。
3:盡量用Handler來處理UIthread和別的thread之間的交互。


ANR完全解析

15剧劝、SharedPreference相關(guān)

  • SharedPreference三種獲得方法和區(qū)別:
1橄登、 Activity類中的getPreferences(int mode)文件自動(dòng)命名為當(dāng)前活動(dòng)的類名。
2、 Context類中g(shù)etSharedPreferences("fileName", int mode) 此方法可以指定文件名拢锹,mode同上谣妻。
3、PreferenceManager類中的getDefaultSharedPreferences(Context context)它只接收一個(gè)context參數(shù)面褐。
文件用當(dāng)前應(yīng)用程序的包名和PreferenceActivity一起來命名拌禾。屬于整個(gè)應(yīng)用程序
SharedPreference獲得方法對(duì)比
  • commit和apply的區(qū)別:
    1. apply沒有返回值而commit返回boolean表明修改是否提交成功。
    2. apply是將修改數(shù)據(jù)原子提交到內(nèi)存, 而后異步真正提交到硬件磁盤, 而commit是同步的提交到硬件磁盤展哭,因此湃窍,在多個(gè)并發(fā)的提交commit的時(shí)候,他們會(huì)等待正在處理的commit保存到磁盤后在操作匪傍,從而降低了效率您市。而apply只是原子的提交到內(nèi)容,后面有調(diào)用apply的函數(shù)的將會(huì)直接覆蓋前面的內(nèi)存數(shù)據(jù)役衡,這樣從一定程度上提高了很多效率茵休。
    3. apply方法不會(huì)提示任何失敗的提示。 由于在一個(gè)進(jìn)程中手蝎,sharedPreference是單實(shí)例榕莺,一般不會(huì)出現(xiàn)并發(fā)沖突,如果對(duì)提交的結(jié)果不關(guān)心的話棵介,建議使用apply钉鸯,當(dāng)然需要確保提交成功且有后續(xù)操作的話,還是需要用commit的邮辽。

16唠雕、View,SurfaceView吨述,GLSurfaceView的關(guān)系和區(qū)別:

  • View:顯示視圖岩睁,內(nèi)置畫布,提供圖形繪制函數(shù)揣云、觸屏事件捕儒、按鍵事件函數(shù)等;必須在UI主線程內(nèi)更新畫面邓夕,速度較慢肋层。
  • SurfaceView:基于view視圖進(jìn)行拓展的視圖類,更適合2D游戲的開發(fā)翎迁;是view的子類,類似使用雙緩機(jī)制净薛,在新的線程中更新畫面所以刷新界面速度比view快汪榔。
  • GLSurfaceView:基于SurfaceView視圖再次進(jìn)行拓展的視圖類,專用于3D游戲開發(fā)的視圖;是SurfaceView的子類痴腌,openGL專用雌团。

17、其他

1士聪、Android 中序列化有哪些方式?區(qū)別?

  • Serializable(Java自帶):
    Serializable是序列化的意思黄刚,表示將一個(gè)對(duì)象轉(zhuǎn)換成可存儲(chǔ)或可傳輸?shù)臓顟B(tài)蹦骑。序列化后的對(duì)象可以在網(wǎng)絡(luò)上進(jìn)行傳輸,也可以存儲(chǔ)到本地区岗。
  • Parcelable(android 專用):
    不過不同于將對(duì)象進(jìn)行序列化略板,Parcelable方式的實(shí)現(xiàn)原理是將一個(gè)完整的對(duì)象進(jìn)行分解,
    而分解后的每一部分都是Intent所支持的數(shù)據(jù)類型
  • 區(qū)別:
    • Parcelable比Serializable性能高慈缔,所以應(yīng)用內(nèi)傳遞數(shù)據(jù)推薦使用Parcelable
    • Serializable代碼量少叮称,寫起來方便,缺點(diǎn)是使用了反射藐鹤,序列化的過程較慢瓤檐。這種機(jī)制會(huì)在序列化的時(shí)候創(chuàng)建許多的臨時(shí)對(duì)象,容易觸發(fā)垃圾回收娱节。

2挠蛉、glide 源碼

3、Android中進(jìn)程的級(jí)別括堤,以及各自的區(qū)別碌秸。

  • 1、前臺(tái)進(jìn)程

用戶當(dāng)前正在做的事情需要這個(gè)進(jìn)程悄窃。如果滿足下面的條件之一讥电,一個(gè)進(jìn)程就被認(rèn)為是前臺(tái)進(jìn)程:
1).這個(gè)進(jìn)程擁有一個(gè)正在與用戶交互的Activity(這個(gè)Activity的onResume()方法被調(diào)用)。
2).這個(gè)進(jìn)程擁有一個(gè)綁定到正在與用戶交互的activity上的Service轧抗。
3).這個(gè)進(jìn)程擁有一個(gè)前臺(tái)運(yùn)行的Service(service調(diào)用了方法startForeground()).
4).這個(gè)進(jìn)程擁有一個(gè)正在執(zhí)行其任何一個(gè)生命周期回調(diào)方法(onCreate(),onStart(),或onDestroy())的Service恩敌。
5).這個(gè)進(jìn)程擁有正在執(zhí)行其onReceive()方法的BroadcastReceiver。
通常横媚,在任何時(shí)間點(diǎn)纠炮,只有很少的前臺(tái)進(jìn)程存在。它們只有在達(dá)到無法調(diào)合的矛盾時(shí)才會(huì)被殺--如內(nèi)存太小而不能繼續(xù)運(yùn)行時(shí)灯蝴。通常恢口,到了這時(shí),設(shè)備就達(dá)到了一個(gè)內(nèi)存分頁調(diào)度狀態(tài)穷躁,所以需要?dú)⒁恍┣芭_(tái)進(jìn)程來保證用戶界面的反應(yīng).

  • 2耕肩、可見進(jìn)程

一個(gè)進(jìn)程不擁有運(yùn)行于前臺(tái)的組件,但是依然能影響用戶所見。滿足下列條件時(shí)猿诸,進(jìn)程即為可見:
這個(gè)進(jìn)程擁有一個(gè)不在前臺(tái)但仍可見的Activity(它的onPause()方法被調(diào)用)婚被。當(dāng)一個(gè)前臺(tái)activity啟動(dòng)一個(gè)對(duì)話框時(shí),就出了這種情況梳虽。

  • 3址芯、服務(wù)進(jìn)程

一個(gè)可見進(jìn)程被認(rèn)為是極其重要的。并且窜觉,除非只有殺掉它才可以保證所有前臺(tái)進(jìn)程的運(yùn)行谷炸,否則是不能動(dòng)它的。
這個(gè)進(jìn)程擁有一個(gè)綁定到可見activity的Service竖螃。
一個(gè)進(jìn)程不在上述兩種之內(nèi)淑廊,但它運(yùn)行著一個(gè)被startService()所啟動(dòng)的service。
盡管一個(gè)服務(wù)進(jìn)程不直接影響用戶所見特咆,但是它們通常做一些用戶關(guān)心的事情(比如播放音樂或下載數(shù)據(jù))季惩,所以系統(tǒng)不到前臺(tái)進(jìn)程和可見進(jìn)程活不下去時(shí)不會(huì)殺它。

  • 4腻格、后臺(tái)進(jìn)程

一個(gè)進(jìn)程擁有一個(gè)當(dāng)前不可見的activity(activity的onStop()方法被調(diào)用)画拾。

  • 5、空進(jìn)程

一個(gè)進(jìn)程不擁有任何active組件菜职。

4青抛、線程池的相關(guān)知識(shí)。

Android中的線程池都是之間或間接通過配置ThreadPoolExecutor來實(shí)現(xiàn)不同特性的線程池.Android中最常見的四類具有不同特性的線程池分別為FixThreadPool酬核、CachedThreadPool蜜另、SingleThreadPool、ScheduleThreadExecutor.

  • FixThreadPool:只有核心線程,并且數(shù)量固定的,也不會(huì)被回收,所有線程都活動(dòng)時(shí),因?yàn)殛?duì)列沒有限制大小,新任務(wù)會(huì)等待執(zhí)行.
    優(yōu)點(diǎn):更快的響應(yīng)外界請(qǐng)求.

  • SingleThreadPool:只有一個(gè)核心線程,確保所有的任務(wù)都在同一線程中按順序完成.因此不需要處理線程同步的問題.

  • CachedThreadPool:只有非核心線程,最大線程數(shù)非常大,所有線程都活動(dòng)時(shí),會(huì)為新任務(wù)創(chuàng)建新線程,否則會(huì)利用空閑線程(60s空閑時(shí)間,過了就會(huì)被回收,所以線程池中有0個(gè)線程的可能)處理任務(wù).
    優(yōu)點(diǎn):任何任務(wù)都會(huì)被立即執(zhí)行(任務(wù)隊(duì)列SynchronousQueue相當(dāng)于一個(gè)空集合);比較適合執(zhí)行大量的耗時(shí)較少的任務(wù).

  • ScheduleThreadExecutor:核心線程數(shù)固定,非核心線程(閑著沒活干會(huì)被立即回收)數(shù)沒有限制.
    優(yōu)點(diǎn):執(zhí)行定時(shí)任務(wù)以及有固定周期的重復(fù)任務(wù)

Android開發(fā)之線程池使用總結(jié)

5嫡意、怎樣計(jì)算一張圖片的大小举瑰,加載bitmap過程(怎樣保證不產(chǎn)生內(nèi)存溢出),二級(jí)緩存蔬螟,LRUCache算法此迅。

1、計(jì)算一張圖片的大小

圖片占用內(nèi)存的計(jì)算公式:圖片高度 * 圖片寬度 * 一個(gè)像素占用的內(nèi)存大小.所以旧巾,計(jì)算圖片占用內(nèi)存大小的時(shí)候耸序,要考慮圖片所在的目錄跟設(shè)備密度,這兩個(gè)因素其實(shí)影響的是圖片的高寬鲁猩,android會(huì)對(duì)圖片進(jìn)行拉升跟壓縮坎怪。

2、加載bitmap過程(怎樣保證不產(chǎn)生內(nèi)存溢出)

由于Android對(duì)圖片使用內(nèi)存有限制廓握,若是加載幾兆的大圖片便內(nèi)存溢出芋忿。
Bitmap會(huì)將圖片的所有像素(即長(zhǎng)x寬)加載到內(nèi)存中炸客,如果圖片分辨率過大,會(huì)直接導(dǎo)致內(nèi)存OOM戈钢,只有在BitmapFactory加載圖片時(shí)使用BitmapFactory.Options對(duì)相關(guān)參數(shù)進(jìn)行配置來減少加載的像素。

3是尔、BitmapFactory.Options相關(guān)參數(shù)詳解

(1).Options.inPreferredConfig值來降低內(nèi)存消耗殉了。
  比如:默認(rèn)值A(chǔ)RGB_8888改為RGB_565,節(jié)約一半內(nèi)存。
(2).設(shè)置Options.inSampleSize 縮放比例拟枚,對(duì)大圖片進(jìn)行壓縮 薪铜。
(3).設(shè)置Options.inPurgeable和inInputShareable:讓系統(tǒng)能及時(shí)回 收內(nèi)存。
  A:inPurgeable:設(shè)置為True時(shí)恩溅,表示系統(tǒng)內(nèi)存不足時(shí)可以被回 收隔箍,設(shè)置為False時(shí),表示不能被回收脚乡。
  B:inInputShareable:設(shè)置是否深拷貝蜒滩,與inPurgeable結(jié)合使用,inPurgeable為false時(shí)奶稠,該參數(shù)無意義俯艰。

(4).使用decodeStream代替其他方法。
decodeResource,setImageResource,setImageBitmap等方法


LRUCache算法:內(nèi)部存在一個(gè)LinkedHashMap和maxSize锌订,把最近使用的對(duì)象用強(qiáng)引用存儲(chǔ)在 LinkedHashMap中竹握,給出來put和get方法,每次put圖片時(shí)計(jì)算緩存中所有圖片總大小辆飘,跟maxSize進(jìn)行比較啦辐,大于maxSize,就將最久添加的圖片移除蜈项;反之小于maxSize就添加進(jìn)來芹关。(400行代碼不到...)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市战得,隨后出現(xiàn)的幾起案子充边,更是在濱河造成了極大的恐慌,老刑警劉巖常侦,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浇冰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡聋亡,警方通過查閱死者的電腦和手機(jī)肘习,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坡倔,“玉大人漂佩,你說我怎么就攤上這事脖含。” “怎么了投蝉?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵养葵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我瘩缆,道長(zhǎng)关拒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任庸娱,我火速辦了婚禮着绊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘熟尉。我一直安慰自己归露,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布斤儿。 她就那樣靜靜地躺著剧包,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雇毫。 梳的紋絲不亂的頭發(fā)上玄捕,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音棚放,去河邊找鬼枚粘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛飘蚯,可吹牛的內(nèi)容都是我干的馍迄。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼局骤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼攀圈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起峦甩,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤赘来,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后凯傲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犬辰,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年冰单,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了幌缝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诫欠,死狀恐怖涵卵,靈堂內(nèi)的尸體忽然破棺而出浴栽,到底是詐尸還是另有隱情,我是刑警寧澤轿偎,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布典鸡,位于F島的核電站,受9級(jí)特大地震影響贴硫,放射性物質(zhì)發(fā)生泄漏椿每。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一英遭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧亦渗,春花似錦挖诸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至搂蜓,卻和暖如春狼荞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背帮碰。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工相味, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人殉挽。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓丰涉,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親斯碌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子一死,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345