極力推薦文章:歡迎收藏
Android 干貨分享
閱讀五分鍾,每日十點,和您一起終身學習,這里是程序員Android
Android
是一種基於Linux
的自由及開放源代碼的操作系統,主要使用於移動設備,如智能手機和平板電腦,由Google
公司和開放手機聯盟領導及開發。這里會不斷收集和更新Android
基礎相關的面試題,目前已收集100
題。
1.Android系統的架構
應用程序
Android
會同一系列核心應用程序包一起發布,該應用程序包包括Email
客戶端,SMS
短消息程序,日歷,地圖,瀏覽器,聯系人管理程序等。所有的應用程序都是使用JAVA
語言編寫的。
應用程序框架
開發人員可以完全訪問核心應用程序所使用的API
框架(android.jar)
。該應用程序的架構設計簡化了組件的重用;任何一個應用程序都可以發布它的功能塊並且任何其它的應用程序都可以使用其所發布的功能塊。
系統運行庫
Android
包含一些C/C++
庫,這些庫能被Android
系統中不同的組件使用。它們通過 Android
應用程序框架為開發者提供服務。
Linux 內核
Android
的核心系統服務依賴於 Linux
內核,如安全性,內存管理,進程管理, 網絡協議棧和驅動模型。 Linux
內核也同時作為硬件和軟件棧之間的抽象層。
2.Activity的生命周期
Activity生命周期方法
主要有onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()和onRestart()
等7個方法。
- 啟動一個
A Activity
,
分別執行onCreate()、onStart()、onResume()
方法。 - 從
A Activity
打開B Activity
分別執行A onPause()、B onCreate()、B onStart()、B onResume()、A onStop()
方法。 - 關閉
B Activity
分別執行B onPause()、A onRestart()、A onStart()、A onResume()、B onStop()、B onDestroy()
方法。 - 橫豎屏切換
A Activity
清單文件中不設置android:configChanges
屬性時,先銷毀onPause()、onStop()、onDestroy()
再重新創建onCreate()、onStart()、onResume()
方法,
設置orientation|screenSize(一定要同時出現)
屬性值時,不走生命周期方法,只會執行onConfigurationChanged()
方法。 Activity
之間的切換
可以看出onPause()、onStop()
這兩個方法比較特殊,切換的時候onPause()
方法不要加入太多耗時操作否則會影響體驗。
3.Fragment的生命周期
Fragment的生命周期
Fragment與Activity生命周期對比
Fragment的生命周期方法
主要有onAttach()、onCreate()、onCreateView()、onActivityCreated()、onstart()、onResume()、onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()
等11個方法。
- 切換到該Fragment
分別執行onAttach()、onCreate()、onCreateView()、onActivityCreated()、onstart()、onResume()
方法。 - 鎖屏
分別執行onPause()、onStop()
方法。 - 亮屏
分別執行onstart()、onResume()
方法。 - 覆蓋切換到其他Fragment
分別執行onPause()、onStop()、onDestroyView()
方法。 - 從其他Fragment回到之前Fragment
分別執行onCreateView()、onActivityCreated()、onstart()、onResume()
方法。
4.Service生命周期
在Service
的生命周期里,常用的有:
4個手動調用的方法
startService() 啟動服務
stopService() 關閉服務
bindService() 綁定服務
unbindService() 解綁服務
5個內部自動調用的方法
onCreat() 創建服務
onStartCommand() 開始服務
onDestroy() 銷毀服務
onBind() 綁定服務
onUnbind() 解綁服務
- 手動調用
startService()
啟動服務,自動調用內部方法:onCreate()、onStartCommand()
,如果一個Service
被startService()
多次啟動,那么onCreate()
也只會調用一次。 - 手動調用
stopService()
關閉服務,自動調用內部方法:onDestory()
,如果一個Service
被啟動且被綁定,如果在沒有解綁的前提下使用stopService()
關閉服務是無法停止服務的。 - 手動調用
bindService()
后,自動調用內部方法:onCreate()、onBind()
。 - 手動調用
unbindService()
后,自動調用內部方法:onUnbind()、onDestory()
。 startService()
和stopService()
只能開啟和關閉Service
,無法操作Service
,調用者退出后Service
仍然存在;bindService()
和unbindService()
可以操作Service
,調用者退出后,Service
隨着調用者銷毀。
5.Android中動畫
Android
中動畫分別幀動畫、補間動畫和屬性動畫(Android 3.0以后的)
幀動畫
幀動畫是最容易實現的一種動畫,這種動畫更多的依賴於完善的UI
資源,他的原理就是將一張張單獨的圖片連貫的進行播放,從而在視覺上產生一種動畫的效果;有點類似於某些軟件制作gif
動畫的方式。在有些代碼中,我們還會看到android:oneshot="false"
,這個oneshot
的含義就是動畫執行一次(true)
還是循環執行多次。
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns: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>
補間動畫
補間動畫又可以分為四種形式,分別是 alpha(淡入淡出)
,translate(位移)
,scale(縮放大小)
,rotate(旋轉)
。
補間動畫的實現,一般會采用xml
文件的形式;代碼會更容易書寫和閱讀,同時也更容易復用。Interpolator
主要作用是可以控制動畫的變化速率 ,就是動畫進行的快慢節奏。pivot
決定了當前動畫執行的參考位置
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
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>
屬性動畫
屬性動畫,顧名思義它是對於對象屬性的動畫。因此,所有補間動畫的內容,都可以通過屬性動畫實現。屬性動畫的運行機制是通過不斷地對值進行操作來實現的,而初始值和結束值之間的動畫過渡就是由ValueAnimator
這個類來負責計算的。它的內部使用一種時間循環的機制來計算值與值之間的動畫過渡,我們只需要將初始值和結束值提供給ValueAnimator
,並且告訴它動畫所需運行的時長,那么ValueAnimator
就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。除此之外,ValueAnimator
還負責管理動畫的播放次數、播放模式、以及對動畫設置監聽器等。
6.Android中4大組件
1. Activity:
Activity
是Android
程序與用戶交互的窗口,是Android
構造塊中最基本的一種,它需要為保持各界面的狀態,做很多持久化的事情,妥善管理生命周期以及一些跳轉邏輯。
2. BroadCast Receiver:
接受一種或者多種Intent
作觸發事件,接受相關消息,做一些簡單處理,轉換成一條Notification
,統一了Android
的事件廣播模型。
3. Content Provider:
是Android
提供的第三方應用數據的訪問方案,可以派生Content Provider
類,對外提供數據,可以像數據庫一樣進行選擇排序,屏蔽內部數據的存儲細節,向外提供統一的接口模型,大大簡化上層應用,對數據的整合提 供了更方便的途徑。
4. service:
后台服務於Activity
,封裝有一個完整的功能邏輯實現,接受上層指令,完成相關的事務,定義好需要接受的Intent
提供同步和異步的接口。
7.Android中常用布局
常用的布局:
FrameLayout(幀布局):
所有東西依次都放在左上角,會重疊
LinearLayout(線性布局):
按照水平和垂直進行數據展示
RelativeLayout(相對布局):
以某一個元素為參照物,來定位的布局方式
不常用的布局:
TableLayout(表格布局):
每一個TableLayout
里面有表格行TableRow
,TableRow
里面可以具體定義每一個元素(Android TV上使用)
AbsoluteLayout(絕對布局):
用X,Y
坐標來指定元素的位置,元素多就不適用。(機頂盒上使用)
`
新增布局:
PercentRelativeLayout(百分比相對布局)
可以通過百分比控制控件的大小。
PercentFrameLayout(百分比幀布局)
可以通過百分比控制控件的大小。
8.消息推送的方式
-
方案1、使用極光和友盟推送。
-
方案2、使用
XMPP
協議(Openfire + Spark + Smack)
- 簡介:基於
XML
協議的通訊協議,前身是Jabber
,目前已由IETF
國際標准化組織完成了標准化工作。 - 優點:協議成熟、強大、可擴展性強、目前主要應用於許多聊天系統中,且已有開源的
Java
版的開發實例androidpn
。
缺點:協議較復雜、冗余(基於XML)
、費流量、費電,部署硬件成本高。
- 簡介:基於
-
方案3、使用
MQTT
協議- 簡介:輕量級的、基於代理的“發布/訂閱”模式的消息傳輸協議。
- 優點:協議簡潔、小巧、可擴展性強、省流量、省電,目前已經應用到企業領域。
- 缺點:不夠成熟、實現較復雜、服務端組件rsmb不開源,部署硬件成本較高。
-
方案4、使用
HTTP
輪循方式- 簡介:定時向
HTTP
服務端接口(Web Service API)
獲取最新消息。 - 優點:實現簡單、可控性強,部署硬件成本低。
- 缺點:實時性差。
- 簡介:定時向
9.Android的數據存儲
1. 使用SharedPreferences
存儲數據
它是Android
提供的用來存儲一些簡單配置信息的一種機制,采用了XML
格式將數據存儲到設備中。只能在同一個包內使用,不能在不同的包之間使用。
2. 文件存儲數據
文件存儲方式是一種較常用的方法,在Android
中讀取/寫入文件
的方法,與Java
中實現I/O
的程序是完全一樣的,提供了openFileInput()
和openFileOutput()
方法來讀取設備上的文件。
3. SQLite數據庫存儲數據
SQLite
是Android
所帶的一個標准的數據庫,它支持SQL
語句,它是一個輕量級的嵌入式數據庫。
4. 使用ContentProvider存儲數據
主要用於應用程序之間進行數據交換,從而能夠讓其他的應用保存或讀取此Content Provider
的各種數據類型。
5. 網絡存儲數據
通過網絡上提供給我們的存儲空間來上傳(存儲)和下載(獲取)我們存儲在網絡空間中的數據信息。
10.Activity啟動模式
介紹 Android
啟動模式之前,先介紹兩個概念task
和taskAffinity
task
翻譯過來就是“任務”,是一組相互有關聯的activity
集合,可以理解為Activity
是在 task
里面活動的。 task
存在於一個稱為 back stack
的數據結構中,也就是說,task
是以棧的形式去管理 activity
的,所以也叫可以稱為任務棧
。
taskAffinity:
官方文檔解釋是:The task that the activity has an affinity for.
,可以翻譯為 activity
相關或者親和的任務,這個參數標識了一個 Activity
所需要的任務棧的名字。默認情況下,所有Activity
所需的任務棧的名字為應用的包名。 taskAffinity
屬性主要和singleTask
啟動模式或者 allowTaskReparenting
屬性配對使用。
4種啟動模式
1. standard標准模式
也是系統默認的啟動模式。假如activity A
啟動了 activity B
,activity B
則會運行在 activity A
所在的任務棧中。而且每次啟動一個 Activity
,都會重新創建新的實例,不管這個實例在任務中是否已經存在。非Activity
類型的 context (如 ApplicationContext )
啟動standard
模式的Activity
時會報錯。非 Activity
類型的 context
並沒有所謂的任務棧,由於上面第 1 點的原因所以系統會報錯。此解決辦法就是為待啟動Activity
指定 FLAG_ACTIVITY_NEW_TASK
標記位,這樣啟動的時候系統就會為它創建一個新的任務棧。這個時候待啟動 Activity
其實是以 singleTask
模式啟動的。
2. singleTop 棧頂復用模式
假如activity A
啟動了 activity B
,就會判斷 A
所在的任務棧棧頂是否是 B
的實例。如果是,則不創建新的 activity B
實例而是直接引用這個棧頂實例,同時 onNewIntent
方法會被回調,通過該方法的參數可以取得當前請求的信息;如果不是,則創建新的 activity B
實例。
3. singleTask 棧內復用模式
在第一次啟動這個 Activity
時,系統便會創建一個新的任務,並且初始化Activity
的實例,放在新任務的底部。不過需要滿足一定條件的。那就是需要設置taskAffinity
屬性。前面也說過了, taskAffinity
屬性是和singleTask
模式搭配使用的。
4. singleInstance 單實例模式
這個是 singleTask
模式的加強版,它除了具有singleTask
模式的所有特性外,它還有一點獨特的特性,那就是此模式的 Activity
只能單獨地位於一個任務棧,不與其他 Activity
共存於同一個任務棧。
11.廣播注冊
首先寫一個類要繼承BroadCastReceiver
第一種:在清單文件中聲明,添加
<receive android:name=".BroadCastReceiverDemo">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED">
</intent-filter>
</receiver>
第二種:使用代碼進行注冊如:
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
BroadCastReceiverDemo receiver = new BroadCastReceiver();
registerReceiver(receiver, filter);
兩種注冊類型的區別是:
a.第一種是常駐型廣播,也就是說當應用程序關閉后,如果有信息廣播來,程序也會被系統調用自動運行。
b.第二種不是常駐廣播,也就是說廣播跟隨程序的生命周期。
12.Android中的ANR
ANR
的全稱application not responding
應用程序未響應。
ANR 類型 | 最長ANR時間 |
---|---|
事件分發(點擊輸入等): | 5s |
BroadcastReceiver | 10s |
Service | 20s` |
超出執行時間就會產生ANR
。注意:ANR
是系統拋出的異常,程序是捕捉不了這個異常的。
解決方法:
- 運行在主線程里的任何方法都盡可能少做事情。特別是,
Activity
應該在它的關鍵生命周期方法(如onCreate()和onResume())
里盡可能少的去做創建操作。可以采用重新開啟子線程的方式,然后使用Handler+Message
的方式做一些操作,比如更新主線程中的ui
等。 - 應用程序應該避免在·BroadcastReceiver·里做耗時的操作或計算。但不再是在子線程里做這些任務
(因為 BroadcastReceiver的生命周期短)
,替代的是,如果響應Intent
廣播需要執行一個耗時的動作的話,應用程序應該啟動一個Service
。
13.ListView優化
1. convertView重用
利用好 convertView
來重用 View
,切忌每次 getView()
都新建。ListView
的核心原理就是重用 View
,如果重用 view
不改變寬高,重用View
可以減少重新分配緩存造成的內存頻繁分配/回收;
2. ViewHolder優化
使用ViewHolder
的原因是findViewById
方法耗時較大,如果控件個數過多,會嚴重影響性能,而使用ViewHolder
主要是為了可以省去這個時間。通過setTag,getTag
直接獲取View
。
3. 減少Item View的布局層級
這是所有Layout
都必須遵循的,布局層級過深會直接導致View
的測量與繪制浪費大量的時間。
4. adapter中的getView方法盡量少使用邏輯
5. 圖片加載采用三級緩存,避免每次都要重新加載。
6. 嘗試開啟硬件加速來使ListView的滑動更加流暢。
7. 使用 RecycleView
代替。
14.Android數字簽名
- 所有的應用程序都必須有數字證書,
Android
系統不會安裝一個沒有數字證書的應用程序 Android
程序包使用的數字證書可以是自簽名的,不需要一個權威的數字證書機構簽名認證- 如果要正式發布一個
Android
,必須使用一個合適的私鑰生成的數字證書來給程序簽名。 - 數字證書都是有有效期的,
Android
只是在應用程序安裝的時候才會檢查證書的有效期。如果程序已經安裝在系統中,即使證書過期也不會影響程序的正常功能。
15.Android root機制
root
指的是你有權限可以再系統上對所有檔案有 "讀" "寫" "執行"的權力。root
機器不是真正能讓你的應用程序具有root
權限。它原理就跟linux
下的像sudo
這樣的命令。在系統的bin
目錄下放個su
程序並屬主是root
並有suid
權限。則通過su
執行的命令都具有Android root
權限。當然使用臨時用戶權限想把su
拷貝的/system/bin
目錄並改屬性並不是一件容易的事情。這里用到2
個工具跟2
個命令。把busybox
拷貝到你有權限訪問的目錄然后給他賦予4755
權限,你就可以用它做很多事了。
16.View、surfaceView、GLSurfaceView
View
顯示視圖,內置畫布,提供圖形繪制函數、觸屏事件、按鍵事件函數等,必須在UI主線程內更新畫面,速度較慢
SurfaceView
基於view
視圖進行拓展的視圖類,更適合2D
游戲的開發,是view
的子類,類似使用雙緩機制,在新的線程中更新畫面所以刷新界面速度比view
快。
GLSurfaceView
基於SurfaceView
視圖再次進行拓展的視圖類,專用於3D
游戲開發的視圖,是surfaceView
的子類,openGL
專用
AsyncTask
AsyncTask的三個泛型參數說明
- 第一個參數:傳入
doInBackground()
方法的參數類型 - 第二個參數:傳入
onProgressUpdate()
方法的參數類型 - 第三個參數:傳入
onPostExecute()
方法的參數類型,也是doInBackground()
方法返回的類型
運行在主線程的方法:
onPostExecute()
onPreExecute()
onProgressUpdate(Progress...)
運行在子線程的方法:
doInBackground()
控制AsyncTask停止的方法:
cancel(boolean mayInterruptIfRunning)
AsyncTask的執行分為四個步驟
- 繼承
AsyncTask。
- 實現
AsyncTask
中定義的下面一個或幾個方法onPreExecute()、doInBackground(Params...)、onProgressUpdate(Progress...)、onPostExecute(Result)
。 - 調用
execute
方法必須在UI thread
中調用。 - 該
task
只能被執行一次,否則多次調用時將會出現異常,取消任務可調用cancel
。
17.Android i18n
I18n
叫做國際化。Android
對i18n
和L10n
提供了非常好的支持。軟件在res/vales
以及 其他帶有語言修飾符的文件夾。如: values-zh
這些文件夾中 提供語言,樣式,尺寸 xml
資源。
18.NDK
NDK
是一系列工具集合,NDK
提供了一系列的工具,幫助開發者迅速的開發C/C++
的動態庫,並能自動將so
和Java
應用打成apk
包。NDK
集成了交叉編譯器,並提供了相應的mk
文件和隔離cpu
、平台等的差異,開發人員只需要簡單的修改mk
文件就可以創建出so
文件。
19.啟動一個程序,可以主界面點擊圖標進入,也可以從一個程序中跳轉過去,二者有什么區別?
通過主界面進入,就是設置默認啟動的activity
。在manifest.xml
文件的activity
標簽中,寫以下代碼
<intent- filter>
<intent android:name=“android.intent.action.MAIN”>
<intent android:name=”android:intent.category.LAUNCHER”>
</intent-filter>
從另一個組件跳轉到目標 activity ,需要通過 intent 進行跳轉。具體
Intent intent=new Intent(this,activity.class),startActivity(intent)
20.內存溢出和內存泄漏有什么區別?何時會產生內存泄漏?
內存溢出:
當程序運行時所需的內存大於程序允許的最高內存,這時會出現內存溢出;
內存泄漏:
在一些比較消耗資源的操作中,如果操作中內存一直未被釋放,就會出現內存泄漏。比如未關閉io,cursor
。
21.sim卡的EF 文件有何作用
sim
卡就是電話卡,sim
卡內有自己的操作系統,用來與手機通訊的。Ef
文件用來存儲數據的。
22.Activity的狀態有幾種?
主要有以下三種狀態:
1.運行
2.暫停
3.停止
23.讓Activity變成一個窗口
設置activity的style
屬性=”@android:style/Theme.Dialog”
<activity
android:name=".CondorMainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Dialog" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
24.android:gravity與android:layout_gravity的區別
gravity:
表示組件內元素的對齊方式
layout_gravity:
相對於父類容器,該視圖組件的對齊方式
25.如何退出Activity
結束當前activity
Finish()
killProgress()
System.exit(0)
關閉應用程序時,結束所有的activity
可以創建一個List
集合,每新創建一個activity
,將該activity
的實例放進list
中,程序結束時,從集合中取出循環取出activity
實例,調用finish()
方法結束
26.如果后台的Activity由於某原因被系統回收了,如何在被系統回收之前保存當前狀態?
在onPuase
方法中調用onSavedInstanceState()
27.Android中的長度單位詳解
Px:
像素
Sp與dp
是長度單位,但是與屏幕的單位密度無關.
28.activity,service,intent之間的關系
這三個都是Android
應用頻率非常的組件。Activity
與service
是四大核心組件。Activity
用來加載布局,顯示窗口界面,service
運行后台,沒有界面顯示,intent
是activity
與service
的通信使者。
29.activity之間傳遞參數,除了intent,廣播接收器,contentProvider之外,還有那些方法?
File:
文件存儲,推薦使用sharedPreferecnces
靜態變量
30.Adapter是什么?你所接觸過的adapter有那些?
是適配器,用來為列表提供數據適配的。經常使用的adapter
有baseadapter
,arrayAdapter,SimpleAdapter,cursorAdapter,SpinnerAdapter
等
31.Fragment與activity如何傳值和交互?
Fragment
對象有一個getActivity()
的方法,通過該方法與activity
交互
使用framentmentManager.findFragmentByXX
可以獲取fragment
對象,在activity
中直接操作fragment
對象。
32.如果Listview中的數據源發生改變,如何更新listview中的數據
使用adapter
的notifyDataSetChanged
方法
33.廣播接受者的生命周期?
廣播接收者的生命周期非常短。當執行onRecieve
方法之后,廣播就會銷毀
在廣播接受者不能進行耗時較長的操作
在廣播接收者不要創建子線程。廣播接收者完成操作后,所在進程會變成空進程,很容易被系統回收
34.ContentProvider與sqlite有什么不一樣的?
ContentProvider 會對外隱藏內部實現,只需要關注訪問
contentProvider的
uri即可,
contentProvider應用在app間共享。
Sqlite操作本應用程序的數據庫。
ContentProiver`可以對本地文件進行增刪改查操作
35.如何保存activity的狀態?
默認情況下activity
的狀態系統會自動保存,有些時候需要我們手動調用保存。
當activity
處於onPause,onStop
之后,activity
處於未活動狀態,但是activity
對象卻仍然存在。當內存不足,onPause,onStop
之后的activity
可能會被系統摧毀。
當通過返回退出activity
時,activity
狀態並不會保存。
保存activity
狀態需要重寫onSavedInstanceState()
方法,在執行onPause,onStop
之前調用onSavedInstanceState
方法,onSavedInstanceState
需要一個Bundle
類型的參數,我們可以將數據保存到bundle
中,通過實參傳遞給onSavedInstanceState
方法。
Activity
被銷毀后,重新啟動時,在onCreate
方法中,接受保存的bundle
參數,並將之前的數據取出。
36.Android中activity,context,application有什么不同。
Content
與application
都繼承與contextWrapper
,contextWrapper
繼承於Context
類。
Context:
表示當前上下文對象,保存的是上下文中的參數和變量,它可以讓更加方便訪問到一些資源。
Context
通常與activity
的生命周期是一樣的,application
表示整個應用程序的對象。
對於一些生命周期較長的,不要使用context
,可以使用application
。
在activity
中,盡量使用靜態內部類,不要使用內部類。內部里作為外部類的成員存在,不是獨立於activity
,如果內存中還有內存繼續引用到context
,activity
如果被銷毀,context
還不會結束。
37.Service 是否在 main thread 中執行, service 里面是否能執行耗時的操作?
默認情況service
在main thread
中執行,當service
在主線程中運行,那在service
中不要進行一些比較耗時的操作,比如說網絡連接,文件拷貝等。
38.Service 和 Activity 在同一個線程嗎
默認情況下service
與activity
在同一個線程,都在main Thread
,或者ui
線程中。
如果在清單文件中指定service
的process
屬性,那么service
就在另一個進程中運行。
39.Service 里面可以彈Toast么
可以。
40.在 service 的生命周期方法 onstartConmand()可不可以執行網絡操作?如何在 service 中執行網絡操作?
可以的,就在onstartConmand
方法內執行。
41.說說 ContentProvider、ContentResolver、ContentObserver 之間的關系
ContentProvider:
內容提供者,對外提供數據的操作,contentProvider.notifyChanged(uir)
:可以更新數據
contentResolver:
內容解析者,解析ContentProvider
返回的數據
ContentObServer:
內容監聽者,監聽數據的改變,contentResolver.registerContentObServer()
42.請介紹下 ContentProvider 是如何實現數據共享的
ContentProvider
是一個對外提供數據的接口,首先需要實現ContentProvider
這個接口,然后重寫query,insert,getType,delete,update
方法,最后在清單文件定義contentProvider
的訪問uri
。
43.Intent 傳遞數據時,可以傳遞哪些類型數據?
1.基本數據類型以及對應的數組類型
2.可以傳遞bundle
類型,但是bundle
類型的數據需要實現Serializable
或者parcelable
接口
44.Serializable 和 Parcelable 的區別?
如果存儲在內存中,推薦使用parcelable
,使用serialiable
在序列化的時候會產生大量的臨時變量,會引起頻繁的GC
如果存儲在硬盤上,推薦使用Serializable
,雖然serializable
效率較低
Serializable的實現:
只需要實現Serializable
接口,就會自動生成一個序列化id
Parcelable的實現:
需要實現Parcelable
接口,還需要Parcelable.CREATER
變量
45.請描述一下 Intent
和 IntentFilter
Intent
是組件的通訊使者,可以在組件間傳遞消息和數據。
IntentFilter
是intent
的篩選器,可以對intent
的action,data,catgory,uri
這些屬性進行篩選,確定符合的目標組件。
46.什么是IntentService?有何優點?
IntentService
是Service
的子類,比普通的 Service
增加了額外的功能。先看Service
本身存在兩個問題:
1.Service
不會專門啟動一條單獨的進程,Service
與它所在應用位於同一個進程中;
2.Service
也不是專門一條新線程,因此不應該在 Service
中直接處理耗時的任務;
特征
會創建獨立的 worker
線程來處理所有的Intent
請求;
會創建獨立的worker
線程來處理 onHandleIntent()
方法實現的代碼,無需處理多線程問題;
所有請求處理完成后,IntentService
會自動停止,無需調用 stopSelf()
方法停止 Service
;
為 Service
的 onBind()
提供默認實現,返回 null
;
為 Service
的 onStartCommand
提供默認實現,將請求 Intent
添加到隊列中
使用
讓 service
類繼承IntentService
,重寫onStartCommand
和onHandleIntent
實現
47.Android 引入廣播機制的用意
從 MVC
的角度考慮(應用程序內) 其實回答這個問題的時候還可以這樣問,android
為什么要有那 4
大組件,現在的移動開發模型基本上也是照搬的 web
那一套 MVC
架構,只不過稍微做了修改。android
的四大組件本質上就是為了實現移動或者說嵌入式設備上的 MVC
架構,它們之間有時候是一種相互依存的關系,有時候又是一種補充關系,引入廣播機制可以方便幾大組件的信息和數據交互。
程序間互通消息(例如在自己的應用程序內監聽系統來電)
效率上(參考UDP
的廣播協議在局域網的方便性)
設計模式上(反轉控制的一種應用,類似監聽者模式)
48.ListView 如何提高其效率?
當 convertView
為空時,用 setTag()
方法為每個 View
綁定一個存放控件的 ViewHolder
對象。當convertView
不為空, 重復利用已經創建的 view
的時候, 使用 getTag()
方法獲取綁定的 ViewHolder
對象,這樣就避免了findViewById
對控件的層層查詢,而是快速定位到控件。 復用 ConvertView
,使用歷史的 view
,提升效率 200%
自定義靜態類 ViewHolder
,減少 findViewById
的次數。提升效率 50%
異步加載數據,分頁加載數據。
使用 WeakRefrence
引用 ImageView
對象
49.ListView 如何實現分頁加載
設置 ListView
的滾動監聽器:setOnScrollListener(new OnScrollListener{….})
在監聽器中有兩個方法: 滾動狀態發生變化的方法(onScrollStateChanged)
和listView
被滾動時調用的方法(onScroll)
在滾動狀態發生改變的方法中,有三種狀態:
手指按下移動的狀態:
SCROLL_STATE_TOUCH_SCROLL
慣性滾動(滑翔(flgin)狀態):
SCROLL_STATE_FLING
:
靜止狀態:
SCROLL_STATE_IDLE:
分批加載數據,只關心靜止狀態:關心最后一個可見的條目,如果最后一個可見條目就是數據適配器(集合)里的最后一個,此時可加載更多的數據。在每次加載的時候,計算出滾動的數量,當滾動的數量大於等於總數量的時候,可以提示用戶無更多數據了。
50.ListView 可以顯示多種類型的條目嗎
這個當然可以的,ListView
顯示的每個條目都是通過 baseAdapter
的 getView(int position,View convertView, ViewGroup parent)
來展示的,理論上我們完全可以讓每個條目都是不同類型的view。
比如:從服務器拿回一個標識為 id=1
,那么當id=1
的時候,我們就加載類型一的條目,當 id=2
的時候,加載類型二的條目。常見布局在資訊類客戶端中可以經常看到。
除此之外 adapter
還提供了 getViewTypeCount()
和 getItemViewType(int position)
兩個方法。在 getView
方法中我們可以根據不同的 viewtype
加載不同的布局文件。
51.ListView 如何定位到指定位置
可以通過 ListView
提供的 lv.setSelection(listView.getPosition())
方法。
52.如何在 ScrollView 中如何嵌入 ListView
通常情況下我們不會在 ScrollView
中嵌套 ListView
。
在 ScrollView
添加一個 ListView
會導致 listview
控件顯示不全,通常只會顯示一條,這是因為兩個控件的滾動事件沖突導致。所以需要通過 listview
中的 item
數量去計算listview
的顯示高度,從而使其完整展示。
現階段最好的處理的方式是: 自定義 ListView
,重載 onMeasure()
方法,設置全部顯示。
53.Manifest.xml文件中主要包括哪些信息?
manifest:
根節點,描述了package
中所有的內容。
uses-permission:
請求你的package
正常運作所需賦予的安全許可。
permission:
聲明了安全許可來限制哪些程序能你package
中的組件和功能。
instrumentation:
聲明了用來測試此package
或其他package
指令組件的代碼。
application:
包含package
中application
級別組件聲明的根節點。
activity:
Activity是用來與用戶交互的主要工具。
receiver:
IntentReceiver
能使的application
獲得數據的改變或者發生的操作,即使它當前不在運行。
service:
Service
是能在后台運行任意時間的組件。
provider:
ContentProvider
是用來管理持久化數據並發布給其他應用程序使用的組件。
54.ListView 中圖片錯位的問題是如何產生的
圖片錯位問題的本質源於我們的 listview
使用了緩存 convertView
, 假設一種場景, 一個 listview
一屏顯示九個 item
,那么在拉出第十個 item
的時候,事實上該item
是重復使用了第一個 item
,也就是說在第一個 item
從網絡中下載圖片並最終要顯示的時候,其實該 item
已經不在當前顯示區域內了,此時顯示的后果將可能在第十個item
上輸出圖像,這就導致了圖片錯位的問題。所以解決辦法就是可見則顯示,不可見則不顯示
。
55.Fragment 的 replace 和 add 方法的區別
Fragment
本身並沒有 replace
和 add
方法,FragmentManager
才有replace
和add
方法。我們經常使用的一個架構就是通過RadioGroup
切換Fragment
,每個 Fragment
就是一個功能模塊。
Fragment
的容器一個 FrameLayout
,add
的時候是把所有的 Fragment
一層一層的疊加到了。FrameLayout
上了,而 replace
的話首先將該容器中的其他Fragment
去除掉然后將當前Fragment
添加到容器中。
一個 Fragment
容器中只能添加一個 Fragment
種類,如果多次添加則會報異常,導致程序終止,而 replace
則無所謂,隨便切換。因為通過 add
的方法添加的 Fragment
,每個 Fragment
只能添加一次,因此如果要想達到切換效果需要通過 Fragment
的的 hide
和 show
方法結合者使用。將要顯示的 show
出來,將其他 hide
起來。這個過程 Fragment
的生命周期沒有變化。
通過 replace
切換 Fragment
,每次都會執行上一個Fragment
的 onDestroyView
,新 Fragment
的 onCreateView、onStart、onResume
方法。基於以上不同的特點我們在使用的使用一定要結合着生命周期操作我們的視圖和數據。
56.Fragment 如何實現類似 Activity 棧的壓棧和出棧效果的?
Fragment
的事物管理器內部維持了一個雙向鏈表結構,該結構可以記錄我們每次 add
的Fragment
和 replace
的 Fragment
,然后當我們點擊 back
按鈕的時候會自動幫我們實現退棧操作。
57.Fragment 在你們項目中的使用
Fragment
是android3.0
以后引入的的概念,做局部內容更新更方便,原來為了到達這一點要把多個布局放到一個 activity
里面,現在可以用多 Fragment
來代替,只有在需要的時候才加載Fragment
,提高性能。
Fragment 的好處:
Fragment
可以使你能夠將 activity
分離成多個可重用的組件,每個都有它自己的生命周期和UI
。
Fragment
可以輕松得創建動態靈活的 UI
設計,可以適應於不同的屏幕尺寸。從手機到平板電腦。
Fragment
是一個獨立的模塊,緊緊地與 activity
綁定在一起。可以運行中動態地移除、加入、交換等。
Fragment
提供一個新的方式讓你在不同的安卓設備上統一你的 UI。
Fragment
解決 Activity
間的切換不流暢,輕量切換。
Fragment
替代TabActivity
做導航,性能更好。
Fragment
在 4.2.
版本中新增嵌套 fragment
使用方法,能夠生成更好的界面效果。
58.如何切換 fragement,不重新實例化
翻看了Android
官方 Doc
,和一些組件的源代碼,發現 replace()
這個方法只是在上一個 Fragment
不再需要時采用的簡便方法.
正確的切換方式是 add()
,切換時 hide()
,add()
另一個 Fragment;再次切換時,只需 hide()
當前,show()
另一個。
這樣就能做到多個 Fragment
切換不重新實例化:
59.如何對 Android 應用進行性能分析
如果不考慮使用其他第三方性能分析工具的話,我們可以直接使用 ddms
中的工具,其實 ddms
工具已經非常的強大了。ddms
中有 traceview、heap、allocation tracker
等工具都可以幫助我們分析應用的方法執行時間效率和內存使用情況。
Traceview
是 Android
平台特有的數據采集和分析工具,它主要用於分析 Android
中應用程序的 hotspot(瓶頸)
。Traceview
本身只是一個數據分析工具,而數據的采集則需要使用 AndroidSDK
中的Debug
類或者利用 DDMS
工具。
heap
工具可以幫助我們檢查代碼中是否存在會造成內存泄漏的地方。
allocation tracker
是內存分配跟蹤工具
60.Android 中如何捕獲未捕獲的異常
UncaughtExceptionHandler
自 定 義 一 個 Application
, 比 如 叫 MyApplication
繼 承 Application
實 現UncaughtExceptionHandler
。
覆寫 UncaughtExceptionHandler
的onCreate
和 uncaughtException
方法。
注意:上面的代碼只是簡單的將異常打印出來。在 onCreate
方法中我們給Thread
類設置默認異常處理 handler
,如果這句代碼不執行則一切都是白搭。在uncaughtException
方法中我們必須新開辟個線程進行我們異常的收集工作,然后將系統給殺死。
在 AndroidManifest
中配置該 Application:<application android:name="com.example.uncatchexception.MyApplication"
Bug 收集工具 Crashlytics
Crashlytics
是專門為移動應用開發者提供的保存和分析應用崩潰的工具。國內主要使用的是友盟做數據統計。
Crashlytics 的好處:
1.Crashlytics
不會漏掉任何應用崩潰信息。
2.Crashlytics
可以像Bug
管理工具那樣,管理這些崩潰日志。
3.Crashlytics
可以每天和每周將崩潰信息匯總發到你的郵箱,所有信息一目了然。
61.如何將SQLite數據庫(dictionary.db文件)與apk文件一起發布
把這個文件放在/res/raw
目錄下即可。res\raw
目錄中的文件不會被壓縮,這樣可以直接提取該目錄中的文件,會生成資源id
。
62.什么是 IntentService?有何優點?
IntentService
是 Service
的子類,比普通的 Service
增加了額外的功能。先看 Service
本身存在兩個問題:
Service
不會專門啟動一條單獨的進程,Service
與它所在應用位於同一個進程中;
Service
也不是專門一條新線程,因此不應該在 Service
中直接處理耗時的任務;
IntentService 特征
會創建獨立的 worker
線程來處理所有的Intent
請求;
會創建獨立的 worker
線程來處理 onHandleIntent()
方法實現的代碼,無需處理多線程問題;
所有請求處理完成后,IntentService
會自動停止,無需調用 stopSelf()
方法停止 Service
;
為 Service
的 onBind()
提供默認實現,返回 null
;
為 Service
的 onStartCommand
提供默認實現,將請求Intent
添加到隊列中;
63.談談對Android NDK的理解
NDK
是一系列工具的集合.NDK
提供了一系列的工具,幫助開發者快速開發C或C++
的動態庫,並能自動將so
和java
應用一起打包成apk.
這些工具對開發者的幫助是巨大的.NDK
集成了交叉編譯器,並提供了相應的mk
文件隔離CPU,平台,ABI
等差異,開發人員只需要簡單修改 mk
文件(指出"哪些文件需要編譯","編譯特性要求"等),就可以創建出so
.
NDK
可以自動地將so
和Java
應用一起打包,極大地減輕了開發人員的打包工作.NDK
提供了一份穩定,功能有限的API
頭文件聲明.
Google
明確聲明該API
是穩定的,在后續所有版本中都穩定支持當前發布的API
.從該版本的NDK
中看出,這些 API
支持的功能非常有限,包含有:C標准庫(libc),標准數學庫(libm ),壓縮庫(libz),Log庫(liblog)
.
64.AsyncTask使用在哪些場景?它的缺陷是什么?如何解決?
AsyncTask
運用的場景就是我們需要進行一些耗時的操作,耗時操作完成后更新主線程,或者在操作過程中對主線程的UI
進行更新。
缺陷:
AsyncTask
中維護着一個長度為128
的線程池,同時可以執行5
個工作線程,還有一個緩沖隊列,當線程池中已有128
個線程,緩沖隊列已滿時,如果 此時向線程提交任務,將會拋出RejectedExecutionException。
解決:
由一個控制線程來處理AsyncTask
的調用判斷線程池是否滿了,如果滿了則線程睡眠否則請求AsyncTask
繼續處理。
65.Android 線程間通信有哪幾種方式(重要)
1.共享內存(變量)
2.文件,數據庫
3.Handler
4.Java
里的 wait(),notify(),notifyAll()
66.請解釋下 Android 程序運行時權限與文件系統權限的區別?
apk
程序是運行在虛擬機上的,對應的是 Android
獨特的權限機制,只有體現到文件系統上時才
使用 linux
的權限設置。
linux
文件系統上的權限
-rwxr-x--x system system 4156 2010-04-30 16:13 test.apk
代表的是相應的用戶/用戶組及其他人對此文件的訪問權限,與此文件運行起來具有的權限完全不相關。比如上面的例子只能說明 system
用戶擁有對此文件的讀寫執行權限;system
組的用戶對此文件擁有讀、執行權限;其他人對此文件只具有執行權限。而 test.apk
運行起來后可以干哪些事情,跟這個就不相關了。千萬不要看 apk
文件系統上屬於 system/system
用戶及用戶組,或者root/root
用戶及用戶組,就認為 apk
具有 system
或 root
權限
Android 的權限規則
Android
中的apk
必須簽名
基於 UserID
的進程級別的安全機制
默認 apk
生成的數據對外是不可見的
AndroidManifest.xml
中的顯式權限聲明
67.Framework 工作方式及原理,Activity 是如何生成一個 view 的,機制是什么?
所有的框架都是基於反射 和 配置文件(manifest)
的。
普通的情況:
Activity
創建一個 view
是通過 ondraw
畫出來的, 畫這個view
之前呢,還會調用 onmeasure
方法來計算顯示的大小.
特殊情況:
Surfaceview
是直接操作硬件的,因為 或者視頻播放對幀數有要求,onDraw
效率太低,不夠使,Surfaceview
直接把數據寫到顯存。
68.什么是 AIDL?如何使用?
aidl
是 Android interface definition Language
的英文縮寫,意思 Android
接口定義語言。
使用aidl
可以幫助我們發布以及調用遠程服務,實現跨進程通信。
將服務的 aidl
放到對應的 src
目錄,工程的 gen
目錄會生成相應的接口類
我們通過 bindService(Intent,ServiceConnect,int)
方法綁定遠程服務,在 bindService
中 有 一 個 ServiceConnect
接 口 , 我 們 需 要 覆 寫 該 類 的onServiceConnected(ComponentName,IBinder)
方法,這個方法的第二個參數IBinder
對象其實就是已經在 aidl
中定義的接口,因此我們可以將 IBinder
對象強制轉換為aidl
中的接口類。我們通過 IBinder
獲取到的對象(也就是 aidl
文件生成的接口)其實是系統產生的代理對象,該代理對象既可以跟我們的進程通信, 又可以跟遠程進程通信, 作為一個中間的角色實現了進程間通信。
69.AIDL 的全稱是什么?如何工作?能處理哪些類型的數據?
AIDL
全稱 Android Interface Definition Language
(AndRoid 接口描述語言) 是一種接口描述語言; 編譯器可以通過 aidl
文件生成一段代碼,通過預先定義的接口達到兩個進程內部通信進程跨界對象訪問的目的。需要完成兩件事情:
1.引入 AIDL
的相關類.;
2.調用aidl
產生的 class
理論上, 參數可以傳遞基本數據類型和 String
, 還有就是 Bundle
的派生類, 不過在Eclipse
中,目前的 ADT
不支持 Bundle
做為參數。
70.Android 判斷SD卡是否存在
/**
* 判斷SD是否掛載
*/
public static boolean isSDCardMount() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
71.Android中任務棧的分配
Task
實際上是一個Activity
棧,通常用戶感受的一個Application
就是一個Task
。從這個定義來看,Task
跟Service
或者其他Components
是沒有任何聯系的,它只是針對Activity
而言的。
Activity
有不同的啟動模式, 可以影響到task
的分配
72.SQLite支持事務嗎? 添加刪除如何提高性能?
在sqlite
插入數據的時候默認一條語句就是一個事務,有多少條數據就有多少次磁盤操作 比如5000
條記錄也就是要5000
次讀寫磁盤操作。
添加事務處理,把多條記錄的插入或者刪除作為一個事務
73.Android中touch事件的傳遞機制是怎樣的?
1.Touch
事件傳遞的相關API
有dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
2.Touch
事件相關的類有View、ViewGroup、Activity
3.Touch
事件會被封裝成MotionEvent
對象,該對象封裝了手勢按下、移動、松開等動作
4.Touch
事件通常從Activity#dispatchTouchEvent
發出,只要沒有被消費,會一直往下傳遞,到最底層的View
。
5.如果Touch
事件傳遞到的每個View
都不消費事件,那么Touch
事件會反向向上傳遞,最終交由Activity#onTouchEvent
處理.
6.onInterceptTouchEvent
為ViewGroup
特有,可以攔截事件.
7.Down
事件到來時,如果一個View
沒有消費該事件,那么后續的MOVE/UP
事件都不會再給它
74.描述下Handler 機制
1)Looper:
一個線程可以產生一個Looper
對象,由它來管理此線程里的MessageQueue(消息隊列)
。
2)Handler:
你可以構造Handler
對象來與Looper
溝通,以便push
新消息到MessageQueue
里;或者接收Looper
從Message Queue
取出所送來的消息。
3) Message Queue(消息隊列):
用來存放線程放入的消息。
4)線程:
UIthread
通常就是main thread
,而Android
啟動程序時會替它建立一個MessageQueue
。
Hander
持有對UI
主線程消息隊列MessageQueue
和消息循環Looper
的引用,子線程可以通過Handler
將消息發送到UI
線程的消息隊列MessageQueue
中。
75.自定義view的基本流程
1.自定義View
的屬性 編寫attr.xml
文件
2.在layout
布局文件中引用,同時引用命名空間
3.在View
的構造方法中獲得我們自定義的屬性 ,在自定義控件中進行讀取(構造方法拿到attr.xml
文件值)
4.重寫onMesure
5.重寫onDraw
76.子線程發消息到主線程進行更新 UI,除了 handler 和 AsyncTask,還有什么?
用 Activity 對象的 runOnUiThread 方法更新
在子線程中通過 runOnUiThread()
方法更新 UI
:
如果在非上下文類中(Activity)
,可以通過傳遞上下文實現調用;
用 View.post(Runnable r)方法更新 UI
77.子線程中能不能 new handler?為什么?
不能,如果在子線程中直接 new Handler()
會拋出異常 java.lang.RuntimeException: Can'tcreate handler inside thread that has not called
78.Android 中的動畫有哪幾類,它們的特點和區別是什么
Frame Animation(幀動畫)
主要用於播放一幀幀准備好的圖片,類似GIF
圖片,優點是使用簡單方便、缺點是需要事先准備好每一幀圖片;
Tween Animation(補間動畫)
僅需定義開始與結束的關鍵幀,而變化的中間幀由系統補上,優點是不用准備每一幀,缺點是只改變了對象繪制,而沒有改變View
本身屬性。因此如果改變了按鈕的位置,還是需要點擊原來按鈕所在位置才有效。
Property Animation(屬性動畫)
是3.0
后推出的動畫,優點是使用簡單、降低實現的復雜度、直接更改對象的屬性、幾乎可適用於任何對象而僅非View
類,主要包括ValueAnimator
和ObjectAnimator
79.如何修改 Activity 進入和退出動畫
可以通過兩種方式
一 是通過定義 Activity
的主題
通過設置主題樣式在styles.xml
中編輯如下代碼:
添加 themes.xml 文件:
在 AndroidManifest.xml 中給指定的 Activity 指定 theme。
二 是通過覆寫 Activity
的overridePendingTransition
方法。
覆寫 overridePendingTransition
方法
overridePendingTransition(R.anim.fade, R.anim.hold);
80.Android與服務器交互的方式中的對稱加密和非對稱加密是什么?
對稱加密,就是加密和解密數據都是使用同一個key
,這方面的算法有DES
。
非對稱加密,加密和解密是使用不同的key
。發送數據之前要先和服務端約定生成公鑰和私鑰,使用公鑰加密的數據可以用私鑰解密,反之。這方面的算法有RSA
。ssh
和 ssl
都是典型的非對稱加密。
82.事件分發中的 onTouch 和 onTouchEvent 有什么區別,又該如何使用?
這兩個方法都是在 View
的 dispatchTouchEvent
中調用的,onTouch
優先於 onTouchEvent
執行。如果在 onTouch
方法中通過返回true
將事件消費掉,onTouchEvent
將不會再執行。
另外需要注意的是,onTouch
能夠得到執行需要兩個前提條件
第一 mOnTouchListener
的值不能為空,
第二當前點擊的控件必須是 enable
的。
因此如果你有一個控件是非 enable
的,那么給它注冊 onTouch
事件將永遠得不到執行。對於這一類控件,如果我們想要監聽它的 touch
事件,就必須通過在該控件中重寫 onTouchEvent
方法來實現。
83.屬性動畫,例如一個 button 從 A 移動到 B 點,B 點還是可以響應點擊事件,這個原理是什么?
補間動畫只是顯示的位置變動,View 的實際位置未改變,表現為 View 移動到其他地方,點擊事件仍在原處才能響應。而屬性動畫控件移動后事件相應就在控件移動后本身進行處理
84.談談你在工作中是怎樣解決一個 bug
異常附近多打印 log
信息;
分析log
日志,實在不行的話進行斷點調試;
調試不出結果,上 Stack Overflow
貼上異常信息,請教大牛
再多看看代碼,或者從源代碼中查找相關信息
實在不行就 GG
了,找師傅來解決!
85.嵌入式操作系統內存管理有哪幾種, 各有何特性
頁式,段式,段頁,用到了MMU
,虛擬空間等技術
86.開發中都使用過哪些框架、平台
- EventBus(事件處理)
- xUtils(網絡、圖片、ORM)
- JPush(推送平台)
- 友盟(統計平台)
- 有米(優米)(廣告平台)
- 百度地圖
- bmob(服務器平台、短信驗證、郵箱驗證、第三方支付)
- 阿里雲 OSS(雲存儲)
- ShareSDK(分享平台、第三方登錄)
- Gson(解析 json 數據框架)
- imageLoader (圖片處理框架)
- zxing (二維碼掃描)
- anroid-asyn-http(網絡通訊)
- DiskLruCache(硬盤緩存框架)
- Viatimo(多媒體播放框架)
- universal-image-loader(圖片緩存框架)
- 訊飛語音(語音識別)
87.談談你對 Bitmap 的理解, 什么時候應該手動調用 bitmap.recycle()
Bitmap
是 android
中經常使用的一個類,它代表了一個圖片資源。 Bitmap
消耗內存很嚴重,如果不注意優化代碼,經常會出現 OOM
問題,優化方式通常有這么幾種:
1.使用緩存;
2.壓縮圖片;
3.及時回收;
至於什么時候需要手動調用 recycle
,這就看具體場景了,原則是當我們不再使用 Bitmap
時,需要回收之。另外,我們需要注意,2.3
之前 Bitmap
對象與像素數據是分開存放的,Bitmap
對象存在java Heap
中而像素數據存放在 Native Memory
中, 這時很有必要調用 recycle
回收內存。 但是 2.3
之后,Bitmap
對象和像素數據都是存在 Heap
中,GC
可以回收其內存。
88.請介紹下 AsyncTask 的內部實現和適用的場景
AsyncTask
內部也是 Handler
機制來完成的,只不過 Android
提供了執行框架來提供線程池來執行相應地任務,因為線程池的大小問題,所以 AsyncTask
只應該用來執行耗時時間較短的任務,比如 HTTP
請求,大規模的下載和數據庫的更改不適用於 AsyncTask
,因為會導致線程池堵塞,沒有線程來執行其他的任務,導致的情形是會發生 AsyncTask
根本執行不了的問題
89.Activity間通過Intent傳遞數據大小有沒有限制?
Intent
在傳遞數據時是有大小限制的,這里官方並未詳細說明,不過通過實驗的方法可以測出數據應該被限制在1MB
之內(1024KB)
,筆者采用的是傳遞Bitmap
的方法,發現當圖片大小超過1024(准確地說是1020左右)
的時候,程序就會出現閃退、停止運行等異常(不同的手機反應不同),因此可以判斷Intent的傳輸容量在1MB
之內。
90.你一般在開發項目中都使用什么設計模式?如何來重構,優化你的代碼?
較為常用的就是單例設計模式,工廠設計模式以及觀察者設計模式,
一般需要保證對象在內存中的唯一性時就是用單例模式,例如對數據庫操作的 SqliteOpenHelper
的對象。
工廠模式主要是為創建對象提供過渡接口,以便將創建對象的具體過程屏蔽隔離起來,達到提高靈活性的目的。
觀察者模式定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新
91.Android 應用中驗證碼登陸都有哪些實現方案
從服務器端獲取圖片
通過短信服務,將驗證碼發送給客戶端
92.定位項目中,如何選取定位方案,如何平衡耗電與實時位置的精度?
開始定位,Application
持有一個全局的公共位置對象,然后隔一定時間自動刷新位置,每次刷新成功都把新的位置信息賦值到全局的位置對象, 然后每個需要使用位置請求的地方都使用全局的位置信息進行請求。
該方案好處:
請求的時候無需再反復定位,每次請求都使用全局的位置對象,節省時間。
該方案弊端:
耗電,每隔一定時間自動刷新位置,對電量的消耗比較大。
按需定位,每次請求前都進行定位。這樣做的好處是比較省電,而且節省資源,但是請求時間會變得相對較長。
93.andorid 應用第二次登錄實現自動登錄
前置條件是所有用戶相關接口都走 https
,非用戶相關列表類數據走 http
。
步驟
第一次登陸 getUserInfo
里帶有一個長效 token
,該長效 token
用來判斷用戶是否登陸和換取短 token
把長效 token
保存到 SharedPreferences
接口請求用長效 token
換取短token
,短 token
服務端可以根據你的接口最后一次請求作為標示,超時時間為一天。
所有接口都用短效 token
如果返回短效 token
失效,執行第3
步,再直接當前接口
如果長效 token
失效(用戶換設備或超過一月),提示用戶登錄。
94.說說 LruCache 底層原理
LruCache
使用一個LinkedHashMap
簡單的實現內存的緩存,沒有軟引用,都是強引用。
如果添加的數據大於設置的最大值,就刪除最先緩存的數據來調整內存。maxSize
是通過構造方法初始化的值,他表示這個緩存能緩存的最大值是多少。
size
在添加和移除緩存都被更新值, 他通過 safeSizeOf
這個方法更新值。 safeSizeOf
默認返回 1
,但一般我們會根據maxSize
重寫這個方法,比如認為maxSize
代表是 KB
的話,那么就以 KB
為單位返回該項所占的內存大小。
除異常外,首先會判斷 size
是否超過 maxSize
,如果超過了就取出最先插入的緩存,如果不為空就刪掉,並把 size
減去該項所占的大小。這個操作將一直循環下去,直到 size
比 maxSize
小或者緩存為空。
95.jni 的調用過程?
安裝和下載 Cygwin
,下載 Android NDK
。
ndk
項目中 JNI
接口的設計。
使用 C/C++
實現本地方法。
JNI
生成動態鏈接庫.so
文件。
將動態鏈接庫復制到 java
工程,在 java
工程中調用,運行 java
工程即可。
96.一條最長的短信息約占多少byte?
中文70(
包括標點),英文160
,160
個字節。
98.即時通訊是是怎么做的?
使用asmark
開源框架實現的即時通訊功能.該框架基於開源的XMPP
即時通信協議,采用 C/S
體系結構,通過GPRS
無線網絡用 TCP
協議連接到服務器,以架設開源的Openfn'e
服務器作為即時通訊平台。
客戶端基於 Android
平台進行開發。負責初始化通信過程,進行即時通信時,由客戶端負責向服務器發起創建連接請求。系統通過GPRS
無線網絡與 Internet 網絡建立連接,通過服務器實現與Android
客戶端的即時通信腳。
服務器端則采用 Openfire
作為服務器。 允許多個客戶端同時登錄並且並發的連接到一個服務器上。服務器對每個客戶端的連接進行認證,對認證通過的客戶端創建會話,客戶端與服務器端之間的通信就在該會話的上下文中進行。
99.怎樣對 android 進行優化?
- 對
listview
的優化。 - 對圖片的優化。
- 對內存的優化。
- 具體一些措施
- 盡量不要使用過多的靜態類
static
- 數據庫使用完成后要記得關閉
cursor
- 廣播使用完之后要注銷
100.如果有個100M大的文件,需要上傳至服務器中,而服務器form表單最大只能上傳2M,可以用什么方法。
首先來說使用http
協議上傳數據,特別在android
下,跟form
沒什么關系。
傳統的在web
中,在form
中寫文件上傳,其實瀏覽器所做的就是將我們的數據進行解析組拼成字符串,以流的方式發送到服務器,且上傳文件用的都是POST
方式,POST
方式對大小沒什么限制。
回到題目,可以說假設每次真的只能上傳2M
,那么可能我們只能把文件截斷,然后分別上傳了,斷點上傳。
至此,本篇已結束,如有不對的地方,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!