Android是一種基于Linux的自由及開放源代碼的操作系統(tǒng)扶关,主要使用于移動設(shè)備妄迁,如智能手機(jī)和平板電腦蛾茉,由Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)垦江。這里會不斷收集和更新Android基礎(chǔ)相關(guān)的面試題,目前已收集100題棠涮。
1.Android系統(tǒng)的架構(gòu)
應(yīng)用程序
Android會同一系列核心應(yīng)用程序包一起發(fā)布谬哀,該應(yīng)用程序包包括Email客戶端,SMS短消息程序严肪,日歷史煎,地圖谦屑,瀏覽器,聯(lián)系人管理程序等篇梭。所有的應(yīng)用程序都是使用JAVA語言編寫的氢橙。
應(yīng)用程序框架
開發(fā)人員可以完全訪問核心應(yīng)用程序所使用的API框架(android.jar)。該應(yīng)用程序的架構(gòu)設(shè)計簡化了組件的重用;任何一個應(yīng)用程序都可以發(fā)布它的功能塊并且任何其它的應(yīng)用程序都可以使用其所發(fā)布的功能塊恬偷。
系統(tǒng)運(yùn)行庫
Android包含一些C/C++庫悍手,這些庫能被Android系統(tǒng)中不同的組件使用。它們通過Android應(yīng)用程序框架為開發(fā)者提供服務(wù)袍患。
Linux 內(nèi)核
Android的核心系統(tǒng)服務(wù)依賴于Linux內(nèi)核坦康,如安全性,內(nèi)存管理诡延,進(jìn)程管理滞欠, 網(wǎng)絡(luò)協(xié)議棧和驅(qū)動模型。Linux內(nèi)核也同時作為硬件和軟件棧之間的抽象層肆良。
2.Activity的生命周期
Activity的生命周期
Activity生命周期方法
主要有onCreate()筛璧、onStart()、onResume()妖滔、onPause()隧哮、onStop()桶良、onDestroy()和onRestart()等7個方法座舍。
啟動一個A Activity,
分別執(zhí)行onCreate()陨帆、onStart()曲秉、onResume()方法带猴。
從A Activity打開B Activity
分別執(zhí)行A onPause()胸嘁、B onCreate()、B onStart()震鹉、B onResume()纲爸、A onStop()方法亥鸠。
關(guān)閉B Activity
分別執(zhí)行B onPause()、A onRestart()识啦、A onStart()负蚊、A onResume()、B onStop()颓哮、B onDestroy()方法家妆。
橫豎屏切換A Activity
清單文件中不設(shè)置android:configChanges屬性時,先銷毀onPause()冕茅、onStop()伤极、onDestroy()再重新創(chuàng)建onCreate()蛹找、onStart()、onResume()方法哨坪,
設(shè)置orientation|screenSize(一定要同時出現(xiàn))屬性值時庸疾,不走生命周期方法,只會執(zhí)行onConfigurationChanged()方法当编。
Activity之間的切換
可以看出onPause()彼硫、onStop()這兩個方法比較特殊,切換的時候onPause()方法不要加入太多耗時操作否則會影響體驗(yàn)凌箕。
3.Fragment的生命周期
Fragment的生命周期
Fragment的生命周期
Fragment與Activity生命周期對比
Fragment的生命周期方法
主要有onAttach()拧篮、onCreate()、onCreateView()牵舱、onActivityCreated()串绩、onstart()、onResume()芜壁、onPause()礁凡、onStop()、onDestroyView()慧妄、onDestroy()顷牌、onDetach()等11個方法。
切換到該Fragment
分別執(zhí)行onAttach()塞淹、onCreate()窟蓝、onCreateView()、onActivityCreated()饱普、onstart()运挫、onResume()方法。
鎖屏
分別執(zhí)行onPause()套耕、onStop()方法谁帕。
亮屏
分別執(zhí)行onstart()、onResume()方法冯袍。
覆蓋切換到其他Fragment
分別執(zhí)行onPause()匈挖、onStop()、onDestroyView()方法康愤。
從其他Fragment回到之前Fragment
分別執(zhí)行onCreateView()儡循、onActivityCreated()、onstart()翘瓮、onResume()方法贮折。
4.Service生命周期
在Service的生命周期里,常用的有:
4個手動調(diào)用的方法
startService()? ? 啟動服務(wù)
stopService()? ? 關(guān)閉服務(wù)
bindService()? ? 綁定服務(wù)
unbindService()? ? 解綁服務(wù)
5個內(nèi)部自動調(diào)用的方法
onCreat()? ? ? ? ? ? 創(chuàng)建服務(wù)
onStartCommand()? ? 開始服務(wù)
onDestroy()? ? ? ? ? ? 銷毀服務(wù)
onBind()? ? ? ? ? ? 綁定服務(wù)
onUnbind()? ? ? ? ? ? 解綁服務(wù)
手動調(diào)用startService()啟動服務(wù)资盅,自動調(diào)用內(nèi)部方法:onCreate()调榄、onStartCommand()踊赠,如果一個Service被startService()多次啟動,那么onCreate()也只會調(diào)用一次每庆。
手動調(diào)用stopService()關(guān)閉服務(wù)筐带,自動調(diào)用內(nèi)部方法:onDestory(),如果一個Service被啟動且被綁定缤灵,如果在沒有解綁的前提下使用stopService()關(guān)閉服務(wù)是無法停止服務(wù)的伦籍。
手動調(diào)用bindService()后,自動調(diào)用內(nèi)部方法:onCreate()腮出、onBind()帖鸦。
手動調(diào)用unbindService()后,自動調(diào)用內(nèi)部方法:onUnbind()胚嘲、onDestory()作儿。
startService()和stopService()只能開啟和關(guān)閉Service,無法操作Service馋劈,調(diào)用者退出后Service仍然存在攻锰;bindService()和unbindService()可以操作Service,調(diào)用者退出后妓雾,Service隨著調(diào)用者銷毀娶吞。
5.Android中動畫
Android中動畫分別幀動畫、補(bǔ)間動畫和屬性動畫(Android 3.0以后的)
幀動畫
幀動畫是最容易實(shí)現(xiàn)的一種動畫械姻,這種動畫更多的依賴于完善的UI資源妒蛇,他的原理就是將一張張單獨(dú)的圖片連貫的進(jìn)行播放,從而在視覺上產(chǎn)生一種動畫的效果策添;有點(diǎn)類似于某些軟件制作gif動畫的方式材部。在有些代碼中毫缆,我們還會看到android:oneshot="false"唯竹,這個oneshot的含義就是動畫執(zhí)行一次(true)還是循環(huán)執(zhí)行多次。
<?xml version="1.0" encoding="utf-8"?>
<animation-listxmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100"/>
<item
android:drawable="@drawable/a_1"
android:duration="100"/>
<item
android:drawable="@drawable/a_2"
android:duration="100"/>
</animation-list>
補(bǔ)間動畫
補(bǔ)間動畫又可以分為四種形式苦丁,分別是alpha(淡入淡出)浸颓,translate(位移),scale(縮放大型)产上,rotate(旋轉(zhuǎn))。
補(bǔ)間動畫的實(shí)現(xiàn)蛾狗,一般會采用xml文件的形式晋涣;代碼會更容易書寫和閱讀,同時也更容易復(fù)用沉桌。Interpolator主要作用是可以控制動畫的變化速率 谢鹊,就是動畫進(jìn)行的快慢節(jié)奏算吩。pivot決定了當(dāng)前動畫執(zhí)行的參考位置
<?xml version="1.0" encoding="utf-8"?>
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float"/>
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float"/>
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float"/>
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float"/>
<set>
...
</set>
</set>
屬性動畫
屬性動畫,顧名思義它是對于對象屬性的動畫佃扼。因此偎巢,所有補(bǔ)間動畫的內(nèi)容,都可以通過屬性動畫實(shí)現(xiàn)兼耀。屬性動畫的運(yùn)行機(jī)制是通過不斷地對值進(jìn)行操作來實(shí)現(xiàn)的压昼,而初始值和結(jié)束值之間的動畫過渡就是由ValueAnimator這個類來負(fù)責(zé)計算的。它的內(nèi)部使用一種時間循環(huán)的機(jī)制來計算值與值之間的動畫過渡瘤运,我們只需要將初始值和結(jié)束值提供給ValueAnimator窍霞,并且告訴它動畫所需運(yùn)行的時長,那么ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結(jié)束值這樣的效果拯坟。除此之外官撼,ValueAnimator還負(fù)責(zé)管理動畫的播放次數(shù)、播放模式似谁、以及對動畫設(shè)置監(jiān)聽器等傲绣。
6.Android中4大組件
1. Activity:
Activity是Android程序與用戶交互的窗口,是Android構(gòu)造塊中最基本的一種巩踏,它需要為保持各界面的狀態(tài)秃诵,做很多持久化的事情,妥善管理生命周期以及一些跳轉(zhuǎn)邏輯塞琼。
2. BroadCast Receiver:
接受一種或者多種Intent作觸發(fā)事件菠净,接受相關(guān)消息,做一些簡單處理彪杉,轉(zhuǎn)換成一條Notification毅往,統(tǒng)一了Android的事件廣播模型。
3. Content Provider:
是Android提供的第三方應(yīng)用數(shù)據(jù)的訪問方案派近,可以派生Content Provider類攀唯,對外提供數(shù)據(jù),可以像數(shù)據(jù)庫一樣進(jìn)行選擇排序渴丸,屏蔽內(nèi)部數(shù)據(jù)的存儲細(xì)節(jié)侯嘀,向外提供統(tǒng)一的接口模型,大大簡化上層應(yīng)用谱轨,對數(shù)據(jù)的整合提 供了更方便的途徑戒幔。
4. service:
后臺服務(wù)于Activity,封裝有一個完整的功能邏輯實(shí)現(xiàn)土童,接受上層指令诗茎,完成相關(guān)的事務(wù),定義好需要接受的Intent提供同步和異步的接口献汗。
7.Android中常用布局
常用的布局:
FrameLayout(幀布局):
所有東西依次都放在左上角敢订,會重疊
LinearLayout(線性布局):
按照水平和垂直進(jìn)行數(shù)據(jù)展示
RelativeLayout(相對布局):
以某一個元素為參照物栅组,來定位的布局方式
不常用的布局:
TableLayout(表格布局):
每一個TableLayout里面有表格行TableRow,TableRow里面可以具體定義每一個元素(Android TV上使用)
AbsoluteLayout(絕對布局):
用X,Y坐標(biāo)來指定元素的位置枢析,元素多就不適用玉掸。(機(jī)頂盒上使用)
`
新增布局:
PercentRelativeLayout(百分比相對布局)
可以通過百分比控制控件的大小。
PercentFrameLayout(百分比幀布局)
可以通過百分比控制控件的大小醒叁。
8.消息推送的方式
方案1司浪、使用極光和友盟推送。
方案2把沼、使用XMPP協(xié)議(Openfire + Spark + Smack)
簡介:基于XML協(xié)議的通訊協(xié)議啊易,前身是Jabber,目前已由IETF國際標(biāo)準(zhǔn)化組織完成了標(biāo)準(zhǔn)化工作饮睬。
優(yōu)點(diǎn):協(xié)議成熟租谈、強(qiáng)大、可擴(kuò)展性強(qiáng)捆愁、目前主要應(yīng)用于許多聊天系統(tǒng)中割去,且已有開源的Java版的開發(fā)實(shí)例androidpn。
缺點(diǎn):協(xié)議較復(fù)雜昼丑、冗余(基于XML)呻逆、費(fèi)流量、費(fèi)電菩帝,部署硬件成本高咖城。
方案3、使用MQTT協(xié)議
簡介:輕量級的呼奢、基于代理的“發(fā)布/訂閱”模式的消息傳輸協(xié)議宜雀。
優(yōu)點(diǎn):協(xié)議簡潔、小巧握础、可擴(kuò)展性強(qiáng)辐董、省流量、省電弓候,目前已經(jīng)應(yīng)用到企業(yè)領(lǐng)域郎哭。
缺點(diǎn):不夠成熟、實(shí)現(xiàn)較復(fù)雜菇存、服務(wù)端組件rsmb不開源,部署硬件成本較高邦蜜。
方案4依鸥、使用HTTP輪循方式
簡介:定時向HTTP服務(wù)端接口(Web Service API)獲取最新消息。
優(yōu)點(diǎn):實(shí)現(xiàn)簡單悼沈、可控性強(qiáng)贱迟,部署硬件成本低姐扮。
缺點(diǎn):實(shí)時性差。
9.Android的數(shù)據(jù)存儲
1. 使用SharedPreferences存儲數(shù)據(jù)
它是Android提供的用來存儲一些簡單配置信息的一種機(jī)制衣吠,采用了XML格式將數(shù)據(jù)存儲到設(shè)備中茶敏。只能在同一個包內(nèi)使用,不能在不同的包之間使用缚俏。
2. 文件存儲數(shù)據(jù)
文件存儲方式是一種較常用的方法惊搏,在Android中讀取/寫入文件的方法,與Java中實(shí)現(xiàn)I/O的程序是完全一樣的忧换,提供了openFileInput()和openFileOutput()方法來讀取設(shè)備上的文件恬惯。
3. SQLite數(shù)據(jù)庫存儲數(shù)據(jù)
SQLite是Android所帶的一個標(biāo)準(zhǔn)的數(shù)據(jù)庫,它支持SQL語句亚茬,它是一個輕量級的嵌入式數(shù)據(jù)庫酪耳。
4. 使用ContentProvider存儲數(shù)據(jù)
主要用于應(yīng)用程序之間進(jìn)行數(shù)據(jù)交換,從而能夠讓其他的應(yīng)用保存或讀取此Content Provider的各種數(shù)據(jù)類型刹缝。
5. 網(wǎng)絡(luò)存儲數(shù)據(jù)
通過網(wǎng)絡(luò)上提供給我們的存儲空間來上傳(存儲)和下載(獲取)我們存儲在網(wǎng)絡(luò)空間中的數(shù)據(jù)信息碗暗。
10.Activity啟動模式
介紹Android啟動模式之前,先介紹兩個概念task和taskAffinity
task
翻譯過來就是“任務(wù)”梢夯,是一組相互有關(guān)聯(lián)的activity集合讹堤,可以理解為Activity是在task里面活動的。task存在于一個稱為back stack的數(shù)據(jù)結(jié)構(gòu)中厨疙,也就是說洲守,task是以棧的形式去管理activity的,所以也叫可以稱為任務(wù)棧沾凄。
taskAffinity:
官方文檔解釋是:The task that the activity has an affinity for.梗醇,可以翻譯為activity相關(guān)或者親和的任務(wù),這個參數(shù)標(biāo)識了一個Activity所需要的任務(wù)棧的名字撒蟀。默認(rèn)情況下叙谨,所有Activity所需的任務(wù)棧的名字為應(yīng)用的包名。taskAffinity屬性主要和singleTask啟動模式或者allowTaskReparenting屬性配對使用保屯。
4種啟動模式
1. standard標(biāo)準(zhǔn)模式
也是系統(tǒng)默認(rèn)的啟動模式手负。假如activity A啟動了activity B,activity B則會運(yùn)行在activity A所在的任務(wù)棧中姑尺。而且每次啟動一個Activity竟终,都會重新創(chuàng)建新的實(shí)例,不管這個實(shí)例在任務(wù)中是否已經(jīng)存在切蟋。非Activity類型的context (如 ApplicationContext )啟動standard模式的Activity時會報錯统捶。非Activity類型的context并沒有所謂的任務(wù)棧,由于上面第 1 點(diǎn)的原因所以系統(tǒng)會報錯。此解決辦法就是為待啟動Activity指定FLAG_ACTIVITY_NEW_TASK標(biāo)記位喘鸟,這樣啟動的時候系統(tǒng)就會為它創(chuàng)建一個新的任務(wù)棧匆绣。這個時候待啟動Activity其實(shí)是以singleTask模式啟動的。
2. singleTop 棧頂復(fù)用模式
假如activity A啟動了activity B什黑,就會判斷A所在的任務(wù)棧棧頂是否是B的實(shí)例崎淳。如果是,則不創(chuàng)建新的activity B實(shí)例而是直接引用這個棧頂實(shí)例愕把,同時onNewIntent方法會被回調(diào)拣凹,通過該方法的參數(shù)可以取得當(dāng)前請求的信息;如果不是礼华,則創(chuàng)建新的activity B實(shí)例咐鹤。
3. singleTask 棧內(nèi)復(fù)用模式
在第一次啟動這個Activity時,系統(tǒng)便會創(chuàng)建一個新的任務(wù)圣絮,并且初始化Activity的實(shí)例祈惶,放在新任務(wù)的底部。不過需要滿足一定條件的扮匠。那就是需要設(shè)置taskAffinity屬性捧请。前面也說過了,taskAffinity屬性是和singleTask模式搭配使用的棒搜。
4. singleInstance 單實(shí)例模式
這個是singleTask模式的加強(qiáng)版疹蛉,它除了具有singleTask模式的所有特性外,它還有一點(diǎn)獨(dú)特的特性力麸,那就是此模式的Activity只能單獨(dú)地位于一個任務(wù)棧可款,不與其他Activity共存于同一個任務(wù)棧。
11.廣播注冊
首先寫一個類要繼承BroadCastReceiver
第一種:在清單文件中聲明克蚂,添加
<receiveandroid:name=".BroadCastReceiverDemo">
<intent-filter>
<actionandroid:name="android.provider.Telephony.SMS_RECEIVED">
</intent-filter>
</receiver>
第二種:使用代碼進(jìn)行注冊如:
IntentFilter filter=newIntentFilter("android.provider.Telephony.SMS_RECEIVED");
BroadCastReceiverDemo receiver=newBroadCastReceiver();
registerReceiver(receiver,filter);
兩種注冊類型的區(qū)別是:
a.第一種是常駐型廣播闺鲸,也就是說當(dāng)應(yīng)用程序關(guān)閉后,如果有信息廣播來埃叭,程序也會被系統(tǒng)調(diào)用自動運(yùn)行摸恍。
b.第二種不是常駐廣播,也就是說廣播跟隨程序的生命周期赤屋。
12.Android中的ANR
ANR的全稱application not responding應(yīng)用程序未響應(yīng)立镶。
ANR 類型最長ANR時間
事件分發(fā)(點(diǎn)擊輸入等):5s
BroadcastReceiver10s
Service20s`
超出執(zhí)行時間就會產(chǎn)生ANR。注意:ANR是系統(tǒng)拋出的異常类早,程序是捕捉不了這個異常的媚媒。
解決方法:
運(yùn)行在主線程里的任何方法都盡可能少做事情。特別是莺奔,Activity應(yīng)該在它的關(guān)鍵生命周期方法(如onCreate()和onResume())里盡可能少的去做創(chuàng)建操作欣范”湫梗可以采用重新開啟子線程的方式令哟,然后使用Handler+Message的方式做一些操作恼琼,比如更新主線程中的ui等。
應(yīng)用程序應(yīng)該避免在·BroadcastReceiver·里做耗時的操作或計算屏富。但不再是在子線程里做這些任務(wù)(因?yàn)?BroadcastReceiver的生命周期短)晴竞,替代的是,如果響應(yīng)Intent廣播需要執(zhí)行一個耗時的動作的話狠半,應(yīng)用程序應(yīng)該啟動一個Service噩死。
13.ListView優(yōu)化
1. convertView重用
利用好convertView來重用View,切忌每次getView()都新建神年。ListView的核心原理就是重用View已维,如果重用view不改變寬高,重用View可以減少重新分配緩存造成的內(nèi)存頻繁分配/回收;
2. ViewHolder優(yōu)化
使用ViewHolder的原因是findViewById方法耗時較大已日,如果控件個數(shù)過多垛耳,會嚴(yán)重影響性能,而使用ViewHolder主要是為了可以省去這個時間飘千。通過setTag堂鲜,getTag直接獲取View。
3. 減少Item View的布局層級
這是所有Layout都必須遵循的护奈,布局層級過深會直接導(dǎo)致View的測量與繪制浪費(fèi)大量的時間缔莲。
4. adapter中的getView方法盡量少使用邏輯
5. 圖片加載采用三級緩存,避免每次都要重新加載霉旗。
6. 嘗試開啟硬件加速來使ListView的滑動更加流暢痴奏。
7. 使用RecycleView代替。
14.Android數(shù)字簽名
所有的應(yīng)用程序都必須有數(shù)字證書厌秒,Android系統(tǒng)不會安裝一個沒有數(shù)字證書的應(yīng)用程序
Android程序包使用的數(shù)字證書可以是自簽名的读拆,不需要一個權(quán)威的數(shù)字證書機(jī)構(gòu)簽名認(rèn)證
如果要正式發(fā)布一個Android,必須使用一個合適的私鑰生成的數(shù)字證書來給程序簽名简僧。
數(shù)字證書都是有有效期的建椰,Android只是在應(yīng)用程序安裝的時候才會檢查證書的有效期。如果程序已經(jīng)安裝在系統(tǒng)中岛马,即使證書過期也不會影響程序的正常功能棉姐。
15.Android root機(jī)制
root指的是你有權(quán)限可以再系統(tǒng)上對所有檔案有 "讀" "寫" "執(zhí)行"的權(quán)力。root機(jī)器不是真正能讓你的應(yīng)用程序具有root權(quán)限啦逆。它原理就跟linux下的像sudo這樣的命令伞矩。在系統(tǒng)的bin目錄下放個su程序并屬主是root并有suid權(quán)限。則通過su執(zhí)行的命令都具有Android root權(quán)限夏志。當(dāng)然使用臨時用戶權(quán)限想把su拷貝的/system/bin目錄并改屬性并不是一件容易的事情乃坤。這里用到2個工具跟2個命令。把busybox拷貝到你有權(quán)限訪問的目錄然后給他賦予4755權(quán)限,你就可以用它做很多事了湿诊。
16.View狱杰、surfaceView、GLSurfaceView
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專用
AsyncTask
AsyncTask的三個泛型參數(shù)說明
第一個參數(shù):傳入doInBackground()方法的參數(shù)類型
第二個參數(shù):傳入onProgressUpdate()方法的參數(shù)類型
第三個參數(shù):傳入onPostExecute()方法的參數(shù)類型,也是doInBackground()方法返回的類型
運(yùn)行在主線程的方法:
onPostExecute()
onPreExecute()
onProgressUpdate(Progress...)
運(yùn)行在子線程的方法:
doInBackground()
控制AsyncTask停止的方法:
cancel(booleanmayInterruptIfRunning)
AsyncTask的執(zhí)行分為四個步驟
繼承AsyncTask坞古。
實(shí)現(xiàn)AsyncTask中定義的下面一個或幾個方法onPreExecute()备韧、doInBackground(Params...)、onProgressUpdate(Progress...)痪枫、onPostExecute(Result)织堂。
調(diào)用execute方法必須在UI thread中調(diào)用。
該task只能被執(zhí)行一次奶陈,否則多次調(diào)用時將會出現(xiàn)異常易阳,取消任務(wù)可調(diào)用cancel。
17.Android i18n
I18n叫做國際化吃粒。Android對i18n和L10n提供了非常好的支持潦俺。軟件在res/vales以及 其他帶有語言修飾符的文件夾。如:values-zh這些文件夾中 提供語言徐勃,樣式事示,尺寸xml資源。
18.NDK
NDK是一系列工具集合僻肖,NDK提供了一系列的工具肖爵,幫助開發(fā)者迅速的開發(fā)C/C++的動態(tài)庫,并能自動將so和Java應(yīng)用打成apk包臀脏。
NDK集成了交叉編譯器劝堪,并提供了相應(yīng)的mk文件和隔離cpu冀自、平臺等的差異,開發(fā)人員只需要簡單的修改mk文件就可以創(chuàng)建出so文件秒啦。
19.啟動一個程序熬粗,可以主界面點(diǎn)擊圖標(biāo)進(jìn)入,也可以從一個程序中跳轉(zhuǎn)過去帝蒿,二者有什么區(qū)別荐糜?
通過主界面進(jìn)入巷怜,就是設(shè)置默認(rèn)啟動的activity葛超。在manifest.xml文件的activity標(biāo)簽中,寫以下代碼
<intent-filter>
<intentandroid:name=“android.intent.action.MAIN”>
<intentandroid:name=”android:intent.category.LAUNCHER”>
</intent-filter>
從另一個組件跳轉(zhuǎn)到目標(biāo) activity 延塑,需要通過 intent 進(jìn)行跳轉(zhuǎn)绣张。具體
Intent intent=newIntent(this,activity.class),startActivity(intent)
20.內(nèi)存溢出和內(nèi)存泄漏有什么區(qū)別?何時會產(chǎn)生內(nèi)存泄漏关带?
內(nèi)存溢出:
當(dāng)程序運(yùn)行時所需的內(nèi)存大于程序允許的最高內(nèi)存侥涵,這時會出現(xiàn)內(nèi)存溢出;
內(nèi)存泄漏:
在一些比較消耗資源的操作中宋雏,如果操作中內(nèi)存一直未被釋放芜飘,就會出現(xiàn)內(nèi)存泄漏。比如未關(guān)閉io,cursor磨总。
21.sim卡的EF 文件有何作用
sim卡就是電話卡嗦明,sim卡內(nèi)有自己的操作系統(tǒng)茁肠,用來與手機(jī)通訊的潘靖。Ef文件用來存儲數(shù)據(jù)的涂炎。
22.Activity的狀態(tài)有幾種绑青?
主要有以下三種狀態(tài):
1.運(yùn)行
2.暫停
3.停止
23.讓Activity變成一個窗口
設(shè)置activity的style屬性=”@android:style/Theme.Dialog”
<activity
android:name=".CondorMainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
24.android:gravity與android:layout_gravity的區(qū)別
gravity:
表示組件內(nèi)元素的對齊方式
layout_gravity:
相對于父類容器赦肃,該視圖組件的對齊方式
25.如何退出Activity
結(jié)束當(dāng)前activity
Finish()
killProgress()
System.exit(0)
關(guān)閉應(yīng)用程序時坪仇,結(jié)束所有的activity
可以創(chuàng)建一個List集合台猴,每新創(chuàng)建一個activity虐骑,將該activity的實(shí)例放進(jìn)list中鲁驶,程序結(jié)束時鉴裹,從集合中取出循環(huán)取出activity實(shí)例,調(diào)用finish()方法結(jié)束
26.如果后臺的Activity由于某原因被系統(tǒng)回收了钥弯,如何在被系統(tǒng)回收之前保存當(dāng)前狀態(tài)径荔?
在onPuase方法中調(diào)用onSavedInstanceState()
27.Android中的長度單位詳解
Px:
像素
Sp與dp
是長度單位,但是與屏幕的單位密度無關(guān).
28.activity寿羞,service猖凛,intent之間的關(guān)系
這三個都是Android應(yīng)用頻率非常的組件。Activity與service是四大核心組件绪穆。Activity用來加載布局辨泳,顯示窗口界面虱岂,service運(yùn)行后臺,沒有界面顯示菠红,intent是activity與service的通信使者第岖。
29.activity之間傳遞參數(shù),除了intent试溯,廣播接收器蔑滓,contentProvider之外,還有那些方法遇绞?
File:
文件存儲键袱,推薦使用sharedPreferecnces
靜態(tài)變量
30.Adapter是什么?你所接觸過的adapter有那些摹闽?
是適配器蹄咖,用來為列表提供數(shù)據(jù)適配的。經(jīng)常使用的adapter有baseadapter付鹿,arrayAdapter澜汤,SimpleAdapter,cursorAdapter,SpinnerAdapter等
31.Fragment與activity如何傳值和交互?
Fragment對象有一個getActivity()的方法舵匾,通過該方法與activity交互
使用framentmentManager.findFragmentByXX可以獲取fragment對象俊抵,在activity中直接操作fragment對象。
32.如果Listview中的數(shù)據(jù)源發(fā)生改變坐梯,如何更新listview中的數(shù)據(jù)
使用adapter的notifyDataSetChanged方法
33.廣播接受者的生命周期徽诲?
廣播接收者的生命周期非常短。當(dāng)執(zhí)行onRecieve方法之后烛缔,廣播就會銷毀
在廣播接受者不能進(jìn)行耗時較長的操作
在廣播接收者不要創(chuàng)建子線程馏段。廣播接收者完成操作后,所在進(jìn)程會變成空進(jìn)程践瓷,很容易被系統(tǒng)回收
34.ContentProvider與sqlite有什么不一樣的院喜?
ContentProvider 會對外隱藏內(nèi)部實(shí)現(xiàn),只需要關(guān)注訪問contentProvider的uri即可晕翠,contentProvider應(yīng)用在app間共享喷舀。Sqlite操作本應(yīng)用程序的數(shù)據(jù)庫。ContentProiver`可以對本地文件進(jìn)行增刪改查操作
35.如何保存activity的狀態(tài)淋肾?
默認(rèn)情況下activity的狀態(tài)系統(tǒng)會自動保存硫麻,有些時候需要我們手動調(diào)用保存。
當(dāng)activity處于onPause樊卓,onStop之后拿愧,activity處于未活動狀態(tài),但是activity對象卻仍然存在碌尔。當(dāng)內(nèi)存不足浇辜,onPause券敌,onStop之后的activity可能會被系統(tǒng)摧毀。
當(dāng)通過返回退出activity時柳洋,activity狀態(tài)并不會保存待诅。
保存activity狀態(tài)需要重寫onSavedInstanceState()方法,在執(zhí)行onPause,onStop之前調(diào)用onSavedInstanceState方法熊镣,onSavedInstanceState需要一個Bundle類型的參數(shù)卑雁,我們可以將數(shù)據(jù)保存到bundle中,通過實(shí)參傳遞給onSavedInstanceState方法绪囱。
Activity被銷毀后测蹲,重新啟動時,在onCreate方法中毕箍,接受保存的bundle參數(shù)弛房,并將之前的數(shù)據(jù)取出。
36.Android中activity而柑,context,application有什么不同荷逞。
Content與application都繼承與contextWrapper媒咳,contextWrapper繼承于Context類。
Context:
表示當(dāng)前上下文對象种远,保存的是上下文中的參數(shù)和變量涩澡,它可以讓更加方便訪問到一些資源。
Context通常與activity的生命周期是一樣的坠敷,application表示整個應(yīng)用程序的對象妙同。
對于一些生命周期較長的,不要使用context膝迎,可以使用application粥帚。
在activity中,盡量使用靜態(tài)內(nèi)部類限次,不要使用內(nèi)部類芒涡。內(nèi)部里作為外部類的成員存在,不是獨(dú)立于activity卖漫,如果內(nèi)存中還有內(nèi)存繼續(xù)引用到context费尽,activity如果被銷毀,context還不會結(jié)束羊始。
37.Service 是否在 main thread 中執(zhí)行, service 里面是否能執(zhí)行耗時的操作?
默認(rèn)情況service在main thread中執(zhí)行旱幼,當(dāng)service在主線程中運(yùn)行,那在service中不要進(jìn)行一些比較耗時的操作突委,比如說網(wǎng)絡(luò)連接柏卤,文件拷貝等叹誉。
38.Service 和 Activity 在同一個線程嗎
默認(rèn)情況下service與activity在同一個線程,都在main Thread闷旧,或者ui線程中长豁。
如果在清單文件中指定service的process屬性,那么service就在另一個進(jìn)程中運(yùn)行忙灼。
39.Service 里面可以彈Toast么
可以匠襟。
40.在 service 的生命周期方法 onstartConmand()可不可以執(zhí)行網(wǎng)絡(luò)操作?如何在 service 中執(zhí)行網(wǎng)絡(luò)操作该园?
可以的酸舍,就在onstartConmand方法內(nèi)執(zhí)行。
41.說說 ContentProvider里初、ContentResolver啃勉、ContentObserver 之間的關(guān)系
ContentProvider:
內(nèi)容提供者,對外提供數(shù)據(jù)的操作双妨,contentProvider.notifyChanged(uir):可以更新數(shù)據(jù)
contentResolver:
內(nèi)容解析者淮阐,解析ContentProvider返回的數(shù)據(jù)
ContentObServer:
內(nèi)容監(jiān)聽者,監(jiān)聽數(shù)據(jù)的改變刁品,contentResolver.registerContentObServer()
42.請介紹下 ContentProvider 是如何實(shí)現(xiàn)數(shù)據(jù)共享的
ContentProvider是一個對外提供數(shù)據(jù)的接口泣特,首先需要實(shí)現(xiàn)ContentProvider這個接口,然后重寫query挑随,insert状您,getType,delete兜挨,update方法膏孟,最后在清單文件定義contentProvider的訪問uri。
43.Intent 傳遞數(shù)據(jù)時拌汇,可以傳遞哪些類型數(shù)據(jù)柒桑?
1.基本數(shù)據(jù)類型以及對應(yīng)的數(shù)組類型
2.可以傳遞bundle類型,但是bundle類型的數(shù)據(jù)需要實(shí)現(xiàn)Serializable或者parcelable接口
44.Serializable 和 Parcelable 的區(qū)別担猛?
如果存儲在內(nèi)存中幕垦,推薦使用parcelable,使用serialiable在序列化的時候會產(chǎn)生大量的臨時變量傅联,會引起頻繁的GC
如果存儲在硬盤上先改,推薦使用Serializable,雖然serializable效率較低
Serializable的實(shí)現(xiàn):
只需要實(shí)現(xiàn)Serializable接口蒸走,就會自動生成一個序列化id
Parcelable的實(shí)現(xiàn):
需要實(shí)現(xiàn)Parcelable接口仇奶,還需要Parcelable.CREATER變量
45.請描述一下Intent和IntentFilter
Intent是組件的通訊使者,可以在組件間傳遞消息和數(shù)據(jù)比驻。
IntentFilter是intent的篩選器该溯,可以對intent的action岛抄,data,catgory狈茉,uri這些屬性進(jìn)行篩選夫椭,確定符合的目標(biāo)組件。
46.什么是IntentService氯庆?有何優(yōu)點(diǎn)蹭秋?
IntentService是Service的子類,比普通的Service增加了額外的功能堤撵。先看Service本身存在兩個問題:
1.Service不會專門啟動一條單獨(dú)的進(jìn)程仁讨,Service與它所在應(yīng)用位于同一個進(jìn)程中;
2.Service也不是專門一條新線程实昨,因此不應(yīng)該在Service中直接處理耗時的任務(wù)洞豁;
特征
會創(chuàng)建獨(dú)立的worker線程來處理所有的Intent請求;
會創(chuàng)建獨(dú)立的worker線程來處理onHandleIntent()方法實(shí)現(xiàn)的代碼荒给,無需處理多線程問題丈挟;
所有請求處理完成后,IntentService會自動停止锐墙,無需調(diào)用stopSelf()方法停止Service礁哄;
為Service的onBind()提供默認(rèn)實(shí)現(xiàn),返回null溪北;
為Service的onStartCommand提供默認(rèn)實(shí)現(xiàn),將請求Intent添加到隊(duì)列中
使用
讓service類繼承IntentService夺脾,重寫onStartCommand和onHandleIntent實(shí)現(xiàn)
47.Android 引入廣播機(jī)制的用意
從MVC的角度考慮(應(yīng)用程序內(nèi)) 其實(shí)回答這個問題的時候還可以這樣問之拨,android為什么要有那4大組件,現(xiàn)在的移動開發(fā)模型基本上也是照搬的web那一套MVC架構(gòu)咧叭,只不過稍微做了修改蚀乔。android的四大組件本質(zhì)上就是為了實(shí)現(xiàn)移動或者說嵌入式設(shè)備上的MVC架構(gòu),它們之間有時候是一種相互依存的關(guān)系菲茬,有時候又是一種補(bǔ)充關(guān)系吉挣,引入廣播機(jī)制可以方便幾大組件的信息和數(shù)據(jù)交互。
程序間互通消息(例如在自己的應(yīng)用程序內(nèi)監(jiān)聽系統(tǒng)來電)
效率上(參考UDP的廣播協(xié)議在局域網(wǎng)的方便性)
設(shè)計模式上(反轉(zhuǎn)控制的一種應(yīng)用婉弹,類似監(jiān)聽者模式)
48.ListView 如何提高其效率睬魂?
當(dāng)convertView為空時,用setTag()方法為每個View綁定一個存放控件的ViewHolder對象镀赌。當(dāng)convertView不為空氯哮, 重復(fù)利用已經(jīng)創(chuàng)建的view的時候, 使用getTag()方法獲取綁定的ViewHolder對象商佛,這樣就避免了findViewById對控件的層層查詢喉钢,而是快速定位到控件姆打。復(fù)用ConvertView,使用歷史的view肠虽,提升效率 200%
自定義靜態(tài)類ViewHolder幔戏,減少findViewById的次數(shù)。提升效率 50%
異步加載數(shù)據(jù)税课,分頁加載數(shù)據(jù)闲延。
使用WeakRefrence引用ImageView對象
49.ListView 如何實(shí)現(xiàn)分頁加載
設(shè)置ListView的滾動監(jiān)聽器:setOnScrollListener(new OnScrollListener{….})在監(jiān)聽器中有兩個方法:滾動狀態(tài)發(fā)生變化的方法(onScrollStateChanged)和listView被滾動時調(diào)用的方法(onScroll)
在滾動狀態(tài)發(fā)生改變的方法中,有三種狀態(tài):
手指按下移動的狀態(tài):
SCROLL_STATE_TOUCH_SCROLL
慣性滾動(滑翔(flgin)狀態(tài)):
SCROLL_STATE_FLING:
靜止?fàn)顟B(tài):
SCROLL_STATE_IDLE:
分批加載數(shù)據(jù)伯复,只關(guān)心靜止?fàn)顟B(tài):關(guān)心最后一個可見的條目慨代,如果最后一個可見條目就是數(shù)據(jù)適配器(集合)里的最后一個,此時可加載更多的數(shù)據(jù)啸如。在每次加載的時候侍匙,計算出滾動的數(shù)量,當(dāng)滾動的數(shù)量大于等于總數(shù)量的時候叮雳,可以提示用戶無更多數(shù)據(jù)了想暗。
50.ListView 可以顯示多種類型的條目嗎
這個當(dāng)然可以的,ListView顯示的每個條目都是通過baseAdapter的getView(int position,View convertView, ViewGroup parent)來展示的帘不,理論上我們完全可以讓每個條目都是不同類型的view说莫。
比如:從服務(wù)器拿回一個標(biāo)識為id=1,那么當(dāng)id=1的時候,我們就加載類型一的條目寞焙,當(dāng)id=2的時候储狭,加載類型二的條目。常見布局在資訊類客戶端中可以經(jīng)车方迹看到辽狈。
除此之外adapter還提供了getViewTypeCount()和getItemViewType(int position)兩個方法。在getView方法中我們可以根據(jù)不同的viewtype加載不同的布局文件呛牲。
51.ListView 如何定位到指定位置
可以通過ListView提供的lv.setSelection(listView.getPosition())方法刮萌。
52.如何在 ScrollView 中如何嵌入 ListView
通常情況下我們不會在ScrollView中嵌套ListView。
在ScrollView添加一個ListView會導(dǎo)致listview控件顯示不全娘扩,通常只會顯示一條着茸,這是因?yàn)閮蓚€控件的滾動事件沖突導(dǎo)致。所以需要通過listview中的item數(shù)量去計算listview的顯示高度琐旁,從而使其完整展示涮阔。
現(xiàn)階段最好的處理的方式是:自定義ListView,重載onMeasure()方法旋膳,設(shè)置全部顯示澎语。
53.Manifest.xml文件中主要包括哪些信息?
manifest:
根節(jié)點(diǎn),描述了package中所有的內(nèi)容擅羞。
uses-permission:
請求你的package正常運(yùn)作所需賦予的安全許可尸变。
permission:
聲明了安全許可來限制哪些程序能你package中的組件和功能。
instrumentation:
聲明了用來測試此package或其他package指令組件的代碼减俏。
application:
包含package中application級別組件聲明的根節(jié)點(diǎn)召烂。
activity:
Activity是用來與用戶交互的主要工具。
receiver:
IntentReceiver能使的application獲得數(shù)據(jù)的改變或者發(fā)生的操作娃承,即使它當(dāng)前不在運(yùn)行奏夫。
service:
Service是能在后臺運(yùn)行任意時間的組件。
provider:
ContentProvider是用來管理持久化數(shù)據(jù)并發(fā)布給其他應(yīng)用程序使用的組件历筝。
54.ListView 中圖片錯位的問題是如何產(chǎn)生的
圖片錯位問題的本質(zhì)源于我們的listview使用了緩存convertView酗昼, 假設(shè)一種場景, 一個listview一屏顯示九個item梳猪,那么在拉出第十個item的時候麻削,事實(shí)上該item是重復(fù)使用了第一個item,也就是說在第一個item從網(wǎng)絡(luò)中下載圖片并最終要顯示的時候春弥,其實(shí)該item已經(jīng)不在當(dāng)前顯示區(qū)域內(nèi)了呛哟,此時顯示的后果將可能在第十個item上輸出圖像,這就導(dǎo)致了圖片錯位的問題匿沛。所以解決辦法就是可見則顯示扫责,不可見則不顯示。
55.Fragment 的 replace 和 add 方法的區(qū)別
Fragment本身并沒有replace和add方法逃呼,F(xiàn)ragmentManager才有replace和add方法鳖孤。我們經(jīng)常使用的一個架構(gòu)就是通過RadioGroup切換Fragment,每個Fragment就是一個功能模塊抡笼。
Fragment的容器一個FrameLayout淌铐,add的時候是把所有的Fragment一層一層的疊加到了。FrameLayout上了蔫缸,而replace的話首先將該容器中的其他Fragment去除掉然后將當(dāng)前Fragment添加到容器中。
一個Fragment容器中只能添加一個Fragment種類际起,如果多次添加則會報異常拾碌,導(dǎo)致程序終止,而replace則無所謂街望,隨便切換校翔。因?yàn)橥ㄟ^add的方法添加的Fragment,每個Fragment只能添加一次灾前,因此如果要想達(dá)到切換效果需要通過Fragment的的hide和show方法結(jié)合者使用防症。將要顯示的show出來,將其他hide起來。這個過程Fragment的生命周期沒有變化蔫敲。
通過replace切換Fragment饲嗽,每次都會執(zhí)行上一個Fragment的onDestroyView,新Fragment的onCreateView奈嘿、onStart貌虾、onResume方法∪褂蹋基于以上不同的特點(diǎn)我們在使用的使用一定要結(jié)合著生命周期操作我們的視圖和數(shù)據(jù)尽狠。
56.Fragment 如何實(shí)現(xiàn)類似 Activity 棧的壓棧和出棧效果的?
Fragment的事物管理器內(nèi)部維持了一個雙向鏈表結(jié)構(gòu)叶圃,該結(jié)構(gòu)可以記錄我們每次add的Fragment和replace的Fragment袄膏,然后當(dāng)我們點(diǎn)擊back按鈕的時候會自動幫我們實(shí)現(xiàn)退棧操作。
57.Fragment 在你們項(xiàng)目中的使用
Fragment是android3.0以后引入的的概念掺冠,做局部內(nèi)容更新更方便沉馆,原來為了到達(dá)這一點(diǎn)要把多個布局放到一個activity里面,現(xiàn)在可以用多Fragment來代替赫舒,只有在需要的時候才加載Fragment悍及,提高性能。
Fragment 的好處:
Fragment可以使你能夠?qū)ctivity分離成多個可重用的組件接癌,每個都有它自己的生命周期和UI心赶。
Fragment可以輕松得創(chuàng)建動態(tài)靈活的UI設(shè)計,可以適應(yīng)于不同的屏幕尺寸缺猛。從手機(jī)到平板電腦缨叫。
Fragment是一個獨(dú)立的模塊,緊緊地與activity綁定在一起±罅牵可以運(yùn)行中動態(tài)地移除耻姥、加入、交換等有咨。
Fragment提供一個新的方式讓你在不同的安卓設(shè)備上統(tǒng)一你的 UI琐簇。
Fragment解決Activity間的切換不流暢,輕量切換座享。
Fragment替代TabActivity做導(dǎo)航婉商,性能更好。
Fragment在4.2.版本中新增嵌套fragment使用方法渣叛,能夠生成更好的界面效果丈秩。
58.如何切換 fragement,不重新實(shí)例化
翻看了Android官方Doc,和一些組件的源代碼淳衙,發(fā)現(xiàn)replace()這個方法只是在上一個Fragment不再需要時采用的簡便方法.
正確的切換方式是add()蘑秽,切換時hide()饺著,add()另一個 Fragment;再次切換時肠牲,只需hide()當(dāng)前幼衰,show()另一個。
這樣就能做到多個Fragment切換不重新實(shí)例化:
59.如何對 Android 應(yīng)用進(jìn)行性能分析
如果不考慮使用其他第三方性能分析工具的話埂材,我們可以直接使用ddms中的工具塑顺,其實(shí)ddms工具已經(jīng)非常的強(qiáng)大了。ddms中有traceview俏险、heap严拒、allocation tracker等工具都可以幫助我們分析應(yīng)用的方法執(zhí)行時間效率和內(nèi)存使用情況。
Traceview是Android平臺特有的數(shù)據(jù)采集和分析工具竖独,它主要用于分析Android中應(yīng)用程序的hotspot(瓶頸)裤唠。Traceview本身只是一個數(shù)據(jù)分析工具,而數(shù)據(jù)的采集則需要使用AndroidSDK中的Debug類或者利用DDMS工具莹痢。
heap工具可以幫助我們檢查代碼中是否存在會造成內(nèi)存泄漏的地方种蘸。
allocation tracker是內(nèi)存分配跟蹤工具
60.Android 中如何捕獲未捕獲的異常
UncaughtExceptionHandler
自 定 義 一 個Application, 比 如 叫MyApplication繼 承Application實(shí) 現(xiàn)UncaughtExceptionHandler竞膳。
覆寫UncaughtExceptionHandler的onCreate和uncaughtException方法航瞭。
注意:上面的代碼只是簡單的將異常打印出來。在onCreate方法中我們給Thread類設(shè)置默認(rèn)異常處理handler坦辟,如果這句代碼不執(zhí)行則一切都是白搭刊侯。在uncaughtException方法中我們必須新開辟個線程進(jìn)行我們異常的收集工作,然后將系統(tǒng)給殺死锉走。
在AndroidManifest中配置該Application:<application android:name="com.example.uncatchexception.MyApplication"
Bug 收集工具 Crashlytics
Crashlytics是專門為移動應(yīng)用開發(fā)者提供的保存和分析應(yīng)用崩潰的工具滨彻。國內(nèi)主要使用的是友盟做數(shù)據(jù)統(tǒng)計。
Crashlytics 的好處:
1.Crashlytics不會漏掉任何應(yīng)用崩潰信息挪蹭。
2.Crashlytics可以像Bug管理工具那樣亭饵,管理這些崩潰日志。
3.Crashlytics可以每天和每周將崩潰信息匯總發(fā)到你的郵箱梁厉,所有信息一目了然辜羊。
61.如何將SQLite數(shù)據(jù)庫(dictionary.db文件)與apk文件一起發(fā)布
把這個文件放在/res/raw目錄下即可。res\raw目錄中的文件不會被壓縮词顾,這樣可以直接提取該目錄中的文件只冻,會生成資源id。
62.什么是 IntentService计技?有何優(yōu)點(diǎn)?
IntentService是Service的子類山橄,比普通的Service增加了額外的功能垮媒。先看Service本身存在兩個問題:
Service不會專門啟動一條單獨(dú)的進(jìn)程舍悯,Service與它所在應(yīng)用位于同一個進(jìn)程中;
Service也不是專門一條新線程睡雇,因此不應(yīng)該在Service中直接處理耗時的任務(wù)萌衬;
IntentService 特征
會創(chuàng)建獨(dú)立的worker線程來處理所有的Intent請求;
會創(chuàng)建獨(dú)立的worker線程來處理onHandleIntent()方法實(shí)現(xiàn)的代碼它抱,無需處理多線程問題秕豫;
所有請求處理完成后,IntentService會自動停止观蓄,無需調(diào)用stopSelf()方法停止Service混移;
為Service的onBind()提供默認(rèn)實(shí)現(xiàn),返回null侮穿;
為Service的onStartCommand提供默認(rèn)實(shí)現(xiàn)歌径,將請求Intent添加到隊(duì)列中;
63.談?wù)剬ndroid NDK的理解
NDK是一系列工具的集合.NDK提供了一系列的工具,幫助開發(fā)者快速開發(fā)C或C++的動態(tài)庫,并能自動將so和java應(yīng)用一起打包成apk.這些工具對開發(fā)者的幫助是巨大的.NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件隔離CPU,平臺,ABI等差異,開發(fā)人員只需要簡單修改mk文件(指出"哪些文件需要編譯","編譯特性要求"等),就可以創(chuàng)建出so.
NDK可以自動地將so和Java應(yīng)用一起打包,極大地減輕了開發(fā)人員的打包工作.NDK提供了一份穩(wěn)定,功能有限的API頭文件聲明.
Google明確聲明該API是穩(wěn)定的,在后續(xù)所有版本中都穩(wěn)定支持當(dāng)前發(fā)布的API.從該版本的NDK中看出,這些API支持的功能非常有限,包含有:C標(biāo)準(zhǔn)庫(libc),標(biāo)準(zhǔn)數(shù)學(xué)庫(libm ),壓縮庫(libz),Log庫(liblog).
64.AsyncTask使用在哪些場景亲茅?它的缺陷是什么回铛?如何解決?
AsyncTask運(yùn)用的場景就是我們需要進(jìn)行一些耗時的操作克锣,耗時操作完成后更新主線程茵肃,或者在操作過程中對主線程的UI進(jìn)行更新。
缺陷:
AsyncTask中維護(hù)著一個長度為128的線程池袭祟,同時可以執(zhí)行5個工作線程验残,還有一個緩沖隊(duì)列,當(dāng)線程池中已有128個線程榕酒,緩沖隊(duì)列已滿時胚膊,如果 此時向線程提交任務(wù),將會拋出RejectedExecutionException想鹰。
解決:
由一個控制線程來處理AsyncTask的調(diào)用判斷線程池是否滿了紊婉,如果滿了則線程睡眠否則請求AsyncTask繼續(xù)處理。
65.Android 線程間通信有哪幾種方式(重要)
1.共享內(nèi)存(變量)
2.文件辑舷,數(shù)據(jù)庫
3.Handler
4.Java里的wait()喻犁,notify(),notifyAll()
66.請解釋下 Android 程序運(yùn)行時權(quán)限與文件系統(tǒng)權(quán)限的區(qū)別何缓?
apk程序是運(yùn)行在虛擬機(jī)上的,對應(yīng)的是Android獨(dú)特的權(quán)限機(jī)制肢础,只有體現(xiàn)到文件系統(tǒng)上時才
使用linux的權(quán)限設(shè)置。
linux文件系統(tǒng)上的權(quán)限
-rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
代表的是相應(yīng)的用戶/用戶組及其他人對此文件的訪問權(quán)限碌廓,與此文件運(yùn)行起來具有的權(quán)限完全不相關(guān)传轰。比如上面的例子只能說明system用戶擁有對此文件的讀寫執(zhí)行權(quán)限;system組的用戶對此文件擁有讀谷婆、執(zhí)行權(quán)限慨蛙;其他人對此文件只具有執(zhí)行權(quán)限辽聊。而test.apk運(yùn)行起來后可以干哪些事情,跟這個就不相關(guān)了期贫。千萬不要看apk文件系統(tǒng)上屬于system/system用戶及用戶組跟匆,或者root/root用戶及用戶組,就認(rèn)為apk具有system或root權(quán)限
Android 的權(quán)限規(guī)則
Android中的apk必須簽名
基于UserID的進(jìn)程級別的安全機(jī)制
默認(rèn)apk生成的數(shù)據(jù)對外是不可見的
AndroidManifest.xml中的顯式權(quán)限聲明
67.Framework 工作方式及原理通砍,Activity 是如何生成一個 view 的玛臂,機(jī)制是什么?
所有的框架都是基于反射 和 配置文件(manifest)的封孙。
普通的情況:
Activity創(chuàng)建一個view是通過ondraw畫出來的, 畫這個view之前呢,還會調(diào)用onmeasure方法來計算顯示的大小.
特殊情況:
Surfaceview是直接操作硬件的迹冤,因?yàn)?或者視頻播放對幀數(shù)有要求,onDraw效率太低敛瓷,不夠使叁巨,Surfaceview直接把數(shù)據(jù)寫到顯存。
68.什么是 AIDL呐籽?如何使用锋勺?
aidl是Android interface definition Language的英文縮寫,意思Android接口定義語言狡蝶。
使用aidl可以幫助我們發(fā)布以及調(diào)用遠(yuǎn)程服務(wù)庶橱,實(shí)現(xiàn)跨進(jìn)程通信。
將服務(wù)的aidl放到對應(yīng)的src目錄贪惹,工程的gen目錄會生成相應(yīng)的接口類
我們通過bindService(Intent苏章,ServiceConnect舅逸,int)方法綁定遠(yuǎn)程服務(wù)餐抢,在bindService中 有 一 個ServiceConnect接 口 , 我 們 需 要 覆 寫 該 類 的onServiceConnected(ComponentName,IBinder)方法芯砸,這個方法的第二個參數(shù)IBinder對象其實(shí)就是已經(jīng)在aidl中定義的接口硼端,因此我們可以將IBinder對象強(qiáng)制轉(zhuǎn)換為aidl中的接口類并淋。我們通過IBinder獲取到的對象(也就是aidl文件生成的接口)其實(shí)是系統(tǒng)產(chǎn)生的代理對象,該代理對象既可以跟我們的進(jìn)程通信珍昨, 又可以跟遠(yuǎn)程進(jìn)程通信县耽, 作為一個中間的角色實(shí)現(xiàn)了進(jìn)程間通信。
69.AIDL 的全稱是什么?如何工作?能處理哪些類型的數(shù)據(jù)镣典?
AIDL全稱Android Interface Definition Language(AndRoid 接口描述語言) 是一種接口描述語言; 編譯器可以通過aidl文件生成一段代碼兔毙,通過預(yù)先定義的接口達(dá)到兩個進(jìn)程內(nèi)部通信進(jìn)程跨界對象訪問的目的。需要完成兩件事情:
1.引入AIDL的相關(guān)類.;
2.調(diào)用aidl產(chǎn)生的class
理論上, 參數(shù)可以傳遞基本數(shù)據(jù)類型和String, 還有就是Bundle的派生類, 不過在Eclipse中,目前的ADT不支持Bundle做為參數(shù)兄春。
70.Android 判斷SD卡是否存在
/**
* 判斷SD是否掛載
*/
publicstaticbooleanisSDCardMount(){
returnEnvironment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
71.Android中任務(wù)棧的分配
Task實(shí)際上是一個Activity棧澎剥,通常用戶感受的一個Application就是一個Task。從這個定義來看赶舆,Task跟Service或者其他Components是沒有任何聯(lián)系的肴裙,它只是針對Activity而言的趾唱。
Activity有不同的啟動模式, 可以影響到task的分配
72.SQLite支持事務(wù)嗎? 添加刪除如何提高性能?
在sqlite插入數(shù)據(jù)的時候默認(rèn)一條語句就是一個事務(wù),有多少條數(shù)據(jù)就有多少次磁盤操作 比如5000條記錄也就是要5000次讀寫磁盤操作蜻懦。
添加事務(wù)處理,把多條記錄的插入或者刪除作為一個事務(wù)
73.Android中touch事件的傳遞機(jī)制是怎樣的?
1.Touch事件傳遞的相關(guān)API有dispatchTouchEvent夕晓、onTouchEvent宛乃、onInterceptTouchEvent
2.Touch事件相關(guān)的類有View、ViewGroup蒸辆、Activity
3.Touch事件會被封裝成MotionEvent對象征炼,該對象封裝了手勢按下、移動躬贡、松開等動作
4.Touch事件通常從Activity#dispatchTouchEvent發(fā)出谆奥,只要沒有被消費(fèi),會一直往下傳遞拂玻,到最底層的View酸些。
5.如果Touch事件傳遞到的每個View都不消費(fèi)事件,那么Touch事件會反向向上傳遞,最終交由Activity#onTouchEvent處理.
6.onInterceptTouchEvent為ViewGroup特有檐蚜,可以攔截事件.
7.Down事件到來時魄懂,如果一個View沒有消費(fèi)該事件,那么后續(xù)的MOVE/UP事件都不會再給它
74.描述下Handler 機(jī)制
1)Looper:
一個線程可以產(chǎn)生一個Looper對象闯第,由它來管理此線程里的MessageQueue(消息隊(duì)列)市栗。
2)Handler:
你可以構(gòu)造Handler對象來與Looper溝通,以便push新消息到MessageQueue里;或者接收Looper從Message Queue取出所送來的消息咳短。
Message Queue(消息隊(duì)列):
用來存放線程放入的消息填帽。
4)線程:
UIthread通常就是main thread,而Android啟動程序時會替它建立一個MessageQueue咙好。
Hander持有對UI主線程消息隊(duì)列MessageQueue和消息循環(huán)Looper的引用篡腌,子線程可以通過Handler將消息發(fā)送到UI線程的消息隊(duì)列MessageQueue中。
75.自定義view的基本流程
1.自定義View的屬性 編寫attr.xml文件
2.在layout布局文件中引用敷扫,同時引用命名空間
3.在View的構(gòu)造方法中獲得我們自定義的屬性 哀蘑,在自定義控件中進(jìn)行讀取(構(gòu)造方法拿到attr.xml文件值)
4.重寫onMesure
5.重寫onDraw
76.子線程發(fā)消息到主線程進(jìn)行更新 UI葵第,除了 handler 和 AsyncTask绘迁,還有什么?
用 Activity 對象的 runOnUiThread 方法更新
在子線程中通過runOnUiThread()方法更新UI:
如果在非上下文類中(Activity)卒密,可以通過傳遞上下文實(shí)現(xiàn)調(diào)用缀台;
用 View.post(Runnable r)方法更新 UI
77.子線程中能不能 new handler?為什么哮奇?
不能,如果在子線程中直接new Handler()會拋出異常java.lang.RuntimeException: Can'tcreate handler inside thread that has not called
78.Android 中的動畫有哪幾類膛腐,它們的特點(diǎn)和區(qū)別是什么
Frame Animation(幀動畫)
主要用于播放一幀幀準(zhǔn)備好的圖片睛约,類似GIF圖片,優(yōu)點(diǎn)是使用簡單方便哲身、缺點(diǎn)是需要事先準(zhǔn)備好每一幀圖片辩涝;
Tween Animation(補(bǔ)間動畫)
僅需定義開始與結(jié)束的關(guān)鍵幀,而變化的中間幀由系統(tǒng)補(bǔ)上勘天,優(yōu)點(diǎn)是不用準(zhǔn)備每一幀怔揩,缺點(diǎn)是只改變了對象繪制,而沒有改變View本身屬性脯丝。因此如果改變了按鈕的位置商膊,還是需要點(diǎn)擊原來按鈕所在位置才有效。
Property Animation(屬性動畫)
是3.0后推出的動畫宠进,優(yōu)點(diǎn)是使用簡單晕拆、降低實(shí)現(xiàn)的復(fù)雜度、直接更改對象的屬性材蹬、幾乎可適用于任何對象而僅非View類实幕,主要包括ValueAnimator和ObjectAnimator
79.如何修改 Activity 進(jìn)入和退出動畫
可以通過兩種方式
一 是通過定義Activity的主題
通過設(shè)置主題樣式在styles.xml中編輯如下代碼:
添加 themes.xml 文件:
在 AndroidManifest.xml 中給指定的 Activity 指定 theme。
二 是通過覆寫Activity的overridePendingTransition方法赚导。
覆寫overridePendingTransition方法
overridePendingTransition(R.anim.fade,R.anim.hold);
80.Android與服務(wù)器交互的方式中的對稱加密和非對稱加密是什么?
對稱加密茬缩,就是加密和解密數(shù)據(jù)都是使用同一個key,這方面的算法有DES吼旧。
非對稱加密凰锡,加密和解密是使用不同的key。發(fā)送數(shù)據(jù)之前要先和服務(wù)端約定生成公鑰和私鑰圈暗,使用公鑰加密的數(shù)據(jù)可以用私鑰解密掂为,反之。這方面的算法有RSA员串。ssh和ssl都是典型的非對稱加密勇哗。
82.事件分發(fā)中的 onTouch 和 onTouchEvent 有什么區(qū)別,又該如何使用寸齐?
這兩個方法都是在View的dispatchTouchEvent中調(diào)用的欲诺,onTouch優(yōu)先于onTouchEvent執(zhí)行。如果在onTouch方法中通過返回true將事件消費(fèi)掉渺鹦,onTouchEvent將不會再執(zhí)行扰法。
另外需要注意的是,onTouch能夠得到執(zhí)行需要兩個前提條件
第一mOnTouchListener的值不能為空毅厚,
第二當(dāng)前點(diǎn)擊的控件必須是enable的塞颁。
因此如果你有一個控件是非enable的,那么給它注冊onTouch事件將永遠(yuǎn)得不到執(zhí)行。對于這一類控件祠锣,如果我們想要監(jiān)聽它的touch事件酷窥,就必須通過在該控件中重寫onTouchEvent方法來實(shí)現(xiàn)。
83.屬性動畫伴网,例如一個 button 從 A 移動到 B 點(diǎn)蓬推,B 點(diǎn)還是可以響應(yīng)點(diǎn)擊事件,這個原理是什么澡腾?
補(bǔ)間動畫只是顯示的位置變動拳氢,View 的實(shí)際位置未改變,表現(xiàn)為 View 移動到其他地方蛋铆,點(diǎn)擊事件仍在原處才能響應(yīng)。而屬性動畫控件移動后事件相應(yīng)就在控件移動后本身進(jìn)行處理
84.談?wù)勀阍诠ぷ髦惺窃鯓咏鉀Q一個 bug
異常附近多打印log信息放接;
分析log日志刺啦,實(shí)在不行的話進(jìn)行斷點(diǎn)調(diào)試;
調(diào)試不出結(jié)果纠脾,上Stack Overflow貼上異常信息玛瘸,請教大牛
再多看看代碼,或者從源代碼中查找相關(guān)信息
實(shí)在不行就GG了苟蹈,找?guī)煾祦斫鉀Q糊渊!
85.嵌入式操作系統(tǒng)內(nèi)存管理有哪幾種, 各有何特性
頁式慧脱,段式渺绒,段頁,用到了MMU,虛擬空間等技術(shù)
86.開發(fā)中都使用過哪些框架菱鸥、平臺
EventBus(事件處理)
xUtils(網(wǎng)絡(luò)宗兼、圖片、ORM)
JPush(推送平臺)
友盟(統(tǒng)計平臺)
有米(優(yōu)米)(廣告平臺)
百度地圖
bmob(服務(wù)器平臺氮采、短信驗(yàn)證殷绍、郵箱驗(yàn)證、第三方支付)
阿里云 OSS(云存儲)
ShareSDK(分享平臺鹊漠、第三方登錄)
Gson(解析 json 數(shù)據(jù)框架)
imageLoader (圖片處理框架)
zxing (二維碼掃描)
anroid-asyn-http(網(wǎng)絡(luò)通訊)
DiskLruCache(硬盤緩存框架)
Viatimo(多媒體播放框架)
universal-image-loader(圖片緩存框架)
訊飛語音(語音識別)
87.談?wù)勀銓?Bitmap 的理解, 什么時候應(yīng)該手動調(diào)用 bitmap.recycle()
Bitmap是android中經(jīng)常使用的一個類主到,它代表了一個圖片資源。Bitmap消耗內(nèi)存很嚴(yán)重躯概,如果不注意優(yōu)化代碼登钥,經(jīng)常會出現(xiàn)OOM問題,優(yōu)化方式通常有這么幾種:
1.使用緩存楞陷;
2.壓縮圖片怔鳖;
3.及時回收;
至于什么時候需要手動調(diào)用recycle,這就看具體場景了结执,原則是當(dāng)我們不再使用Bitmap時度陆,需要回收之。另外献幔,我們需要注意懂傀,2.3之前Bitmap對象與像素數(shù)據(jù)是分開存放的,Bitmap對象存在java Heap中而像素數(shù)據(jù)存放在Native Memory中蜡感, 這時很有必要調(diào)用recycle回收內(nèi)存蹬蚁。但是2.3之后,Bitmap對象和像素數(shù)據(jù)都是存在Heap中郑兴,GC可以回收其內(nèi)存犀斋。
88.請介紹下 AsyncTask 的內(nèi)部實(shí)現(xiàn)和適用的場景
AsyncTask內(nèi)部也是Handler機(jī)制來完成的,只不過Android提供了執(zhí)行框架來提供線程池來執(zhí)行相應(yīng)地任務(wù)情连,因?yàn)榫€程池的大小問題叽粹,所以AsyncTask只應(yīng)該用來執(zhí)行耗時時間較短的任務(wù),比如HTTP請求却舀,大規(guī)模的下載和數(shù)據(jù)庫的更改不適用于AsyncTask虫几,因?yàn)闀?dǎo)致線程池堵塞,沒有線程來執(zhí)行其他的任務(wù)挽拔,導(dǎo)致的情形是會發(fā)生AsyncTask根本執(zhí)行不了的問題
89.Activity間通過Intent傳遞數(shù)據(jù)大小有沒有限制辆脸?
Intent在傳遞數(shù)據(jù)時是有大小限制的,這里官方并未詳細(xì)說明螃诅,不過通過實(shí)驗(yàn)的方法可以測出數(shù)據(jù)應(yīng)該被限制在1MB之內(nèi)(1024KB)啡氢,筆者采用的是傳遞Bitmap的方法,發(fā)現(xiàn)當(dāng)圖片大小超過1024(準(zhǔn)確地說是1020左右)的時候州刽,程序就會出現(xiàn)閃退空执、停止運(yùn)行等異常(不同的手機(jī)反應(yīng)不同),因此可以判斷Intent的傳輸容量在1MB之內(nèi)穗椅。
90.你一般在開發(fā)項(xiàng)目中都使用什么設(shè)計模式辨绊?如何來重構(gòu),優(yōu)化你的代碼匹表?
較為常用的就是單例設(shè)計模式门坷,工廠設(shè)計模式以及觀察者設(shè)計模式,
一般需要保證對象在內(nèi)存中的唯一性時就是用單例模式,例如對數(shù)據(jù)庫操作的SqliteOpenHelper的對象。
工廠模式主要是為創(chuàng)建對象提供過渡接口袍镀,以便將創(chuàng)建對象的具體過程屏蔽隔離起來默蚌,達(dá)到提高靈活性的目的。
觀察者模式定義對象間的一種一對多的依賴關(guān)系苇羡,當(dāng)一個對象的狀態(tài)發(fā)生改變時绸吸,所有依賴于它的對象都得到通知并被自動更新
91.Android 應(yīng)用中驗(yàn)證碼登陸都有哪些實(shí)現(xiàn)方案
從服務(wù)器端獲取圖片
通過短信服務(wù),將驗(yàn)證碼發(fā)送給客戶端
92.定位項(xiàng)目中,如何選取定位方案锦茁,如何平衡耗電與實(shí)時位置的精度攘轩?
開始定位,Application持有一個全局的公共位置對象码俩,然后隔一定時間自動刷新位置度帮,每次刷新成功都把新的位置信息賦值到全局的位置對象, 然后每個需要使用位置請求的地方都使用全局的位置信息進(jìn)行請求稿存。
該方案好處:
請求的時候無需再反復(fù)定位笨篷,每次請求都使用全局的位置對象,節(jié)省時間瓣履。
該方案弊端:
耗電率翅,每隔一定時間自動刷新位置,對電量的消耗比較大袖迎。
按需定位安聘,每次請求前都進(jìn)行定位。這樣做的好處是比較省電瓢棒,而且節(jié)省資源,但是請求時間會變得相對較長丘喻。
93.andorid 應(yīng)用第二次登錄實(shí)現(xiàn)自動登錄
前置條件是所有用戶相關(guān)接口都走h(yuǎn)ttps脯宿,非用戶相關(guān)列表類數(shù)據(jù)走h(yuǎn)ttp。
步驟
第一次登陸getUserInfo里帶有一個長效token泉粉,該長效token用來判斷用戶是否登陸和換取短token
把長效token保存到SharedPreferences
接口請求用長效token換取短token连霉,短token服務(wù)端可以根據(jù)你的接口最后一次請求作為標(biāo)示,超時時間為一天嗡靡。
所有接口都用短效token
如果返回短效token失效跺撼,執(zhí)行第3步,再直接當(dāng)前接口
如果長效token失效(用戶換設(shè)備或超過一月)讨彼,提示用戶登錄歉井。
94.說說 LruCache 底層原理
LruCache使用一個LinkedHashMap簡單的實(shí)現(xiàn)內(nèi)存的緩存,沒有軟引用哈误,都是強(qiáng)引用哩至。
如果添加的數(shù)據(jù)大于設(shè)置的最大值,就刪除最先緩存的數(shù)據(jù)來調(diào)整內(nèi)存蜜自。maxSize是通過構(gòu)造方法初始化的值菩貌,他表示這個緩存能緩存的最大值是多少。
size在添加和移除緩存都被更新值重荠, 他通過safeSizeOf這個方法更新值箭阶。safeSizeOf默認(rèn)返回1,但一般我們會根據(jù)maxSize重寫這個方法,比如認(rèn)為maxSize代表是KB的話仇参,那么就以KB為單位返回該項(xiàng)所占的內(nèi)存大小嘹叫。
除異常外,首先會判斷size是否超過maxSize冈敛,如果超過了就取出最先插入的緩存待笑,如果不為空就刪掉,并把size減去該項(xiàng)所占的大小抓谴。這個操作將一直循環(huán)下去暮蹂,直到size比maxSize小或者緩存為空。
95.jni 的調(diào)用過程?
安裝和下載Cygwin癌压,下載Android NDK仰泻。
ndk項(xiàng)目中JNI接口的設(shè)計。
使用C/C++實(shí)現(xiàn)本地方法滩届。
JNI生成動態(tài)鏈接庫.so文件集侯。
將動態(tài)鏈接庫復(fù)制到j(luò)ava工程,在java工程中調(diào)用帜消,運(yùn)行java工程即可棠枉。
96.一條最長的短信息約占多少byte?
中文70(包括標(biāo)點(diǎn)),英文160泡挺,160個字節(jié)辈讶。
98.即時通訊是是怎么做的?
使用asmark開源框架實(shí)現(xiàn)的即時通訊功能.該框架基于開源的XMPP即時通信協(xié)議,采用C/S體系結(jié)構(gòu)娄猫,通過GPRS無線網(wǎng)絡(luò)用TCP協(xié)議連接到服務(wù)器贱除,以架設(shè)開源的Openfn'e服務(wù)器作為即時通訊平臺。
客戶端基于Android平臺進(jìn)行開發(fā)媳溺。負(fù)責(zé)初始化通信過程月幌,進(jìn)行即時通信時,由客戶端負(fù)責(zé)向服務(wù)器發(fā)起創(chuàng)建連接請求悬蔽。系統(tǒng)通過GPRS無線網(wǎng)絡(luò)與 Internet 網(wǎng)絡(luò)建立連接扯躺,通過服務(wù)器實(shí)現(xiàn)與Android客戶端的即時通信腳。
服務(wù)器端則采用Openfire作為服務(wù)器蝎困。允許多個客戶端同時登錄并且并發(fā)的連接到一個服務(wù)器上缅帘。服務(wù)器對每個客戶端的連接進(jìn)行認(rèn)證,對認(rèn)證通過的客戶端創(chuàng)建會話难衰,客戶端與服務(wù)器端之間的通信就在該會話的上下文中進(jìn)行钦无。
99.怎樣對 android 進(jìn)行優(yōu)化?
對listview的優(yōu)化盖袭。
對圖片的優(yōu)化失暂。
對內(nèi)存的優(yōu)化彼宠。
具體一些措施
盡量不要使用過多的靜態(tài)類static
數(shù)據(jù)庫使用完成后要記得關(guān)閉cursor
廣播使用完之后要注銷
100.如果有個100M大的文件,需要上傳至服務(wù)器中弟塞,而服務(wù)器form表單最大只能上傳2M凭峡,可以用什么方法。
首先來說使用http協(xié)議上傳數(shù)據(jù)决记,特別在android下摧冀,跟form沒什么關(guān)系。
傳統(tǒng)的在web中系宫,在form中寫文件上傳索昂,其實(shí)瀏覽器所做的就是將我們的數(shù)據(jù)進(jìn)行解析組拼成字符串,以流的方式發(fā)送到服務(wù)器扩借,且上傳文件用的都是POST方式椒惨,POST方式對大小沒什么限制。
回到題目潮罪,可以說假設(shè)每次真的只能上傳2M康谆,那么可能我們只能把文件截斷,然后分別上傳了嫉到,斷點(diǎn)上傳沃暗。