1、請解釋下在單線程模型中Message,Handler,Message Queue,Looper之間的關(guān)系。
拿主線程來說,主線程啟動(dòng)時(shí)會(huì)調(diào)用Looper.prepare()方法,會(huì)初始化一個(gè)Looper,放入Threadlocal中,接著調(diào)用Looper.loop()不斷遍歷Message Queue,
Handler的創(chuàng)建依賴與當(dāng)前線程中的Looper,如果當(dāng)前線程沒有Looper則必須調(diào)用Looper.prepare()。Handler , sendMessage到MessageQueue,Looper不斷
從MessageQueue中取出消息,回調(diào)handleMessage方法。
2、如果有個(gè)100M大的文件,需要上傳至服務(wù)器中,而服務(wù)器form表單最大只能上傳2M,可以用什么方法。
這個(gè)問題不是很明確我覺得,首先來說使用http協(xié)議上傳數(shù)據(jù),特別在[android](http://lib.csdn.net/base/android)下,跟form沒什么關(guān)系。傳統(tǒng)的在web中,在form中寫文件上傳,其實(shí)瀏覽器所做
的就是將我們的數(shù)據(jù)進(jìn)行解析組拼成字符串,以流的方式發(fā)送到服務(wù)器,且上傳文件用的都是POST方式,POST方式對大小沒什么限制。
回到題目,可以說假設(shè)每次真的只能上傳2M,那么可能我們只能把文件截?cái)啵缓蠓謩e上傳了。
3、內(nèi)存溢出和內(nèi)存泄漏有什么區(qū)別?何時(shí)會(huì)產(chǎn)生內(nèi)存泄漏?內(nèi)存優(yōu)化有哪些方法?
內(nèi)存溢出通俗理解就是軟件(應(yīng)用)運(yùn)行需要的內(nèi)存,超出了它可用的最大內(nèi)存。
內(nèi)存泄漏就是我們對某一內(nèi)存空間的使用,使用完成后沒有釋放。
內(nèi)存優(yōu)化:Android中容易內(nèi)存溢出的部分,就是圖片的加載,我們可以使用圖片的壓縮加上使用LruCache緩存的目的來控制圖片所能夠使用的內(nèi)存。
還有對于比較耗資源的對象及時(shí)的關(guān)閉,例如Database Conn , 各種傳感器 , Service 等等。
4、AsyncTask使用在哪些場景?它的缺陷是什么?如何解決?
AsyncTask 運(yùn)用的場景就是我們需要進(jìn)行一些耗時(shí)的操作,耗時(shí)操作完成后更新主線程,或者在操作過程中對主線程的UI進(jìn)行更新。
缺陷:AsyncTask中維護(hù)著一個(gè)長度為128的線程池,同時(shí)可以執(zhí)行5個(gè)工作線程,還有一個(gè)緩沖隊(duì)列,當(dāng)線程池中已有128個(gè)線程,緩沖隊(duì)列已滿時(shí),如果
此時(shí)向線程提交任務(wù),將會(huì)拋出RejectedExecutionException。
解決:由一個(gè)控制線程來處理AsyncTask的調(diào)用判斷線程池是否滿了,如果滿了則線程睡眠否則請求AsyncTask繼續(xù)處理。
Activity間通過Intent傳遞數(shù)據(jù)大小有沒有限制?
貌似是40K。
8、 啟動(dòng)一個(gè)程序,可以主界面點(diǎn)擊圖標(biāo)進(jìn)入,也可以從一個(gè)程序中跳轉(zhuǎn)過去,二者有什么區(qū)別?
是因?yàn)閱?dòng)程序(主界面也是一個(gè)app),發(fā)現(xiàn)了在這個(gè)程序中存在一個(gè)設(shè)置為<category android:name="android.intent.category.LAUNCHER" />的activity,
所以這個(gè)launcher會(huì)把icon提出來,放在主界面上。當(dāng)用戶點(diǎn)擊icon的時(shí)候,發(fā)出一個(gè)Intent:
Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);
跳過去可以跳到任意允許的頁面,如一個(gè)程序可以下載,那么真正下載的頁面可能不是首頁(也有可能是首頁),這時(shí)還是構(gòu)造一個(gè)Intent,startActivity.
這個(gè)intent中的action可能有多種view,download都有可能。系統(tǒng)會(huì)根據(jù)第三方程序向系統(tǒng)注冊的功能,為你的Intent選擇可以打開的程序或者頁面。所以唯一的一點(diǎn)
不同的是從icon的點(diǎn)擊啟動(dòng)的intent的action是相對單一的,從程序中跳轉(zhuǎn)或者啟動(dòng)可能樣式更多一些。本質(zhì)是相同的。
11、橫豎屏切換時(shí)候Activity的生命周期。
1、不設(shè)置Activity的android:configChanges時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行兩次
2、設(shè)置Activity的android:configChanges="orientation"時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫、豎屏?xí)r只會(huì)執(zhí)行一次
3、設(shè)置Activity的android:configChanges="orientation|keyboardHidden"時(shí),切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行onConfigurationChanged方法
12、AIDL的全稱是什么?如何工作?
全稱是:Android Interface Define Language
在Android中, 每個(gè)應(yīng)用程序都可以有自己的進(jìn)程. 在寫UI應(yīng)用的時(shí)候, 經(jīng)常要用到Service. 在不同的進(jìn)程中, 怎樣傳遞對象呢? 顯然, [Java](http://lib.csdn.net/base/java)中不允許跨進(jìn)程內(nèi)存共享.
因此傳遞對象, 只能把對象拆分成[操作系統(tǒng)](http://lib.csdn.net/base/operatingsystem)能理解的簡單形式, 以達(dá)到跨界對象訪問的目的. 在J2EE中,采用RMI的方式, 可以通過序列化傳遞對象. 在Android中, 則
采用AIDL的方式. 理論上AIDL可以傳遞Bundle,實(shí)際上做起來卻比較麻煩。
AIDL(AndRoid接口描述語言)是一種借口描述語言; 編譯器可以通過aidl文件生成一段代碼,通過預(yù)先定義的接口達(dá)到兩個(gè)進(jìn)程內(nèi)部通信進(jìn)程的目的. 如果需要
在一個(gè)Activity中, 訪問另一個(gè)Service中的某個(gè)對象, 需要先將對象轉(zhuǎn)化成AIDL可識(shí)別的參數(shù)(可能是多個(gè)參數(shù)), 然后使用AIDL來傳遞這些參數(shù), 在消息的接收端, 使用
這些參數(shù)組裝成自己需要的對象.AIDL的IPC的機(jī)制和COM或CORBA類似, 是基于接口的,但它是輕量級的。它使用代理類在客戶端和實(shí)現(xiàn)層間傳遞值. 如果要使用AIDL,
需要完成2件事情: 1. 引入AIDL的相關(guān)類.; 2. 調(diào)用aidl產(chǎn)生的class.
AIDL的創(chuàng)建方法:
AIDL語法很簡單,可以用來聲明一個(gè)帶一個(gè)或多個(gè)方法的接口,也可以傳遞參數(shù)和返回值。 由于遠(yuǎn)程調(diào)用的需要, 這些參數(shù)和返回值并不是任何類型.
下面是些AIDL支持的數(shù)據(jù)類型:
1. 不需要import聲明的簡單Java編程語言類型(int,boolean等)
2. String, CharSequence不需要特殊聲明
3. List, Map和Parcelables類型, 這些類型內(nèi)所包含的數(shù)據(jù)成員也只能是簡單數(shù)據(jù)類型, String等其他比支持的類型.
(另外: 我沒嘗試Parcelables, 在Eclipse+ADT下編譯不過, 或許以后會(huì)有所支持
1、 Android的四大組件是哪些,它們的作用?
答:Activity:Activity是Android程序與用戶交互的窗口,是Android構(gòu)造塊中最基本的一種,它需要為保持各界面的狀態(tài),做很多持久化的事情,妥善管理生命周期以及一些跳轉(zhuǎn)邏輯
service:后臺(tái)服務(wù)于Activity,封裝有一個(gè)完整的功能邏輯實(shí)現(xiàn),接受上層指令,完成相關(guān)的事物,定義好需要接受的Intent提供同步和異步的接口
Content Provider:是Android提供的第三方應(yīng)用數(shù)據(jù)的訪問方案,可以派生Content Provider類,對外提供數(shù)據(jù),可以像數(shù)據(jù)庫一樣進(jìn)行選擇排序,屏蔽內(nèi)部數(shù)據(jù)的存儲(chǔ)細(xì)節(jié),向外提供統(tǒng)一的借口模型,大大簡化上層應(yīng)用,對數(shù)據(jù)的整合提供了更方便的途徑
BroadCast Receiver:接受一種或者多種Intent作觸發(fā)事件,接受相關(guān)消息,做一些簡單處理,轉(zhuǎn)換成一條Notification,統(tǒng)一了Android的事件廣播模型
2、 請介紹下Android中常用的五種布局。
常用五種布局方式,分別是:FrameLayout(框架布局),LinearLayout (線性布局),AbsoluteLayout(絕對布局),RelativeLayout(相對布局),TableLayout(表格布局)。
一、FrameLayout:所有東西依次都放在左上角,會(huì)重疊,這個(gè)布局比較簡單,也只能放一點(diǎn)比較簡單的東西。
二、LinearLayout:線性布局,每一個(gè)LinearLayout里面又可分為垂直布局(android:orientation="vertical")和水平布局(android:orientation="horizontal" )。當(dāng)垂直布局時(shí),每一行就只有一個(gè)元素,多個(gè)元素依次垂直往下;水平布局時(shí),只有一行,每一個(gè)元素依次向右排列。
三、AbsoluteLayout:絕對布局用X,Y坐標(biāo)來指定元素的位置,這種布局方式也比較簡單,但是在屏幕旋轉(zhuǎn)時(shí),往往會(huì)出問題,而且多個(gè)元素的時(shí)候,計(jì)算比較麻煩。
四、RelativeLayout:相對布局可以理解為某一個(gè)元素為參照物,來定位的布局方式。主要屬性有:相對于某一個(gè)元素android:layout_below、 android:layout_toLeftOf相對于父元素的地方android:layout_alignParentLeft、android:layout_alignParentRigh;
五、TableLayout:表格布局,每一個(gè)TableLayout里面有表格行TableRow,TableRow里面可以具體定義每一個(gè)元素。每一個(gè)布局都有自己適合的方式,這五個(gè)布局元素可以相互嵌套應(yīng)用,做出美觀的界面。
3、 android中的動(dòng)畫有哪幾類,它們的特點(diǎn)和區(qū)別是什么
兩種,一種是Tween動(dòng)畫、還有一種是Frame動(dòng)畫。Tween動(dòng)畫,這種實(shí)現(xiàn)方式可以使視圖組件移動(dòng)、放大、縮小以及產(chǎn)生透明度的變化;另一種Frame動(dòng)畫,傳統(tǒng)的動(dòng)畫方法,通過順序的播放排列好的圖片來實(shí)現(xiàn),類似電影。
android 中有哪幾種解析xml的類?官方推薦哪種?以及它們的原理和區(qū)別。
XML解析主要有三種方式,SAX、DOM、PULL。常規(guī)在PC上開發(fā)我們使用Dom相對輕松些,但一些性能敏感的數(shù)據(jù)庫或手機(jī)上還是主要采用SAX方式,SAX讀取是單向的,優(yōu)點(diǎn):不占內(nèi)存空間、解析屬性方便,但缺點(diǎn)就是對于套嵌多個(gè)分支來說處理不是很方便。而DOM方式會(huì)把整個(gè)XML文件加載到內(nèi)存中去,這里Android開發(fā)網(wǎng)提醒大家該方法在查找方面可以和XPath很好的結(jié)合如果數(shù)據(jù)量不是很大推薦使用,而PULL常常用在J2ME對于節(jié)點(diǎn)處理比較好,類似SAX方式,同樣很節(jié)省內(nèi)存,在J2ME中我們經(jīng)常使用的KXML庫來解析。
ListView的優(yōu)化方案
1、如果自定義適配器,那么在getView方法中要考慮方法傳進(jìn)來的參數(shù)contentView是否為null,如果為null就創(chuàng)建contentView并返回,如果不為null則直接使用。在這個(gè)方法中盡可能少創(chuàng)建view。
2、給contentView設(shè)置tag(setTag()),傳入一個(gè)viewHolder對象,用于緩存要顯示的數(shù)據(jù),可以達(dá)到圖像數(shù)據(jù)異步加載的效果。
3、如果listview需要顯示的item很多,就要考慮分頁加載。比如一共要顯示100條或者更多的時(shí)候,我們可以考慮先加載20條,等用戶拉到列表底部的時(shí)候再去加載接下來的20條。
Android的數(shù)據(jù)存儲(chǔ)方式
使用SharedPreferences存儲(chǔ)數(shù)據(jù);
文件存儲(chǔ)數(shù)據(jù);
SQLite數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù);
使用ContentProvider存儲(chǔ)數(shù)據(jù);
網(wǎng)絡(luò)存儲(chǔ)數(shù)據(jù);
Preference,F(xiàn)ile, DataBase這三種方式分別對應(yīng)的目錄是/data/data/Package Name/Shared_Pref, /data/data/Package Name/files, /data/data/Package Name/database 。
一:使用SharedPreferences存儲(chǔ)數(shù)據(jù)
首先說明SharedPreferences存儲(chǔ)方式,它是 Android提供的用來存儲(chǔ)一些簡單配置信息的一種機(jī)制,例如:登錄用戶的用戶名與密碼。其采用了Map數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)數(shù)據(jù),以鍵值的方式存儲(chǔ),可以簡單的讀取與寫入,具體實(shí)例如下:
void
ReadSharedPreferences(){
String strName,strPassword;
SharedPreferences user = getSharedPreferences(“user_info”,
0
);
strName = user.getString(“NAME”,””);
strPassword = user getString(“PASSWORD”,””);
}
void
WriteSharedPreferences(String strName,String strPassword){
SharedPreferences user = getSharedPreferences(“user_info”,
0
);
uer.edit();
user.putString(“NAME”, strName);
user.putString(“PASSWORD” ,strPassword);
user.commit();
}
數(shù)據(jù)讀取與寫入的方法都非常簡單,只是在寫入的時(shí)候有些區(qū)別:先調(diào)用edit()使其處于編輯狀態(tài),然后才能修改數(shù)據(jù),最后使用commit()提交修改的數(shù)據(jù)。實(shí)際上SharedPreferences是采用了XML格式將數(shù)據(jù)存儲(chǔ)到設(shè)備中,在DDMS中的File Explorer中的/data/data/<package name>/shares_prefs下。使用SharedPreferences是有些限制的:只能在同一個(gè)包內(nèi)使用,不能在不同的包之間使用。
二:文件存儲(chǔ)數(shù)據(jù)
文件存儲(chǔ)方式是一種較常用的方法,在Android中讀取/寫入文件的方法,與 Java中實(shí)現(xiàn)I/O的程序是完全一樣的,提供了openFileInput()和openFileOutput()方法來讀取設(shè)備上的文件。具體實(shí)例如下:
String fn = “moandroid.log”;
FileInputStream fis = openFileInput(fn);
FileOutputStream fos = openFileOutput(fn,Context.MODE_PRIVATE);
三:網(wǎng)絡(luò)存儲(chǔ)數(shù)據(jù)
網(wǎng)絡(luò)存儲(chǔ)方式,需要與Android 網(wǎng)絡(luò)數(shù)據(jù)包打交道,關(guān)于Android 網(wǎng)絡(luò)數(shù)據(jù)包的詳細(xì)說明,請閱讀Android SDK引用了Java SDK的哪些package?。
四:ContentProvider
1、ContentProvider簡介
當(dāng)應(yīng)用繼承ContentProvider類,并重寫該類用于提供數(shù)據(jù)和存儲(chǔ)數(shù)據(jù)的方法,就可以向其他應(yīng)用共享其數(shù)據(jù)。雖然使用其他方法也可以對外共享數(shù)據(jù),但數(shù)據(jù)訪問方式會(huì)因數(shù)據(jù)存儲(chǔ)的方式而不同,如:采用文件方式對外共享數(shù)據(jù),需要進(jìn)行文件操作讀寫數(shù)據(jù);采用sharedpreferences共享數(shù)據(jù),需要使用sharedpreferences API讀寫數(shù)據(jù)。而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問方式。
2、Uri類簡介
Uri代表了要操作的數(shù)據(jù),Uri主要包含了兩部分信息:1.需要操作的ContentProvider ,2.對ContentProvider中的什么數(shù)據(jù)進(jìn)行操作,一個(gè)Uri由以下幾部分組成:
1.scheme:ContentProvider(內(nèi)容提供者)的scheme已經(jīng)由Android所規(guī)定為:content://…
2.主機(jī)名(或Authority):用于唯一標(biāo)識(shí)這個(gè)ContentProvider,外部調(diào)用者可以根據(jù)這個(gè)標(biāo)識(shí)來找到它。
3.路徑(path):可以用來表示我們要操作的數(shù)據(jù),路徑的構(gòu)建應(yīng)根據(jù)業(yè)務(wù)而定,如下:
要操作contact表中id為10的記錄,可以構(gòu)建這樣的路徑:/contact/10
要操作contact表中id為10的記錄的name字段, contact/10/name
要操作contact表中的所有記錄,可以構(gòu)建這樣的路徑:/contact?
要操作的數(shù)據(jù)不一定來自數(shù)據(jù)庫,也可以是文件等他存儲(chǔ)方式,如下:
要操作xml文件中contact節(jié)點(diǎn)下的name節(jié)點(diǎn),可以構(gòu)建這樣的路徑:/contact/name
如果要把一個(gè)字符串轉(zhuǎn)換成Uri,可以使用Uri類中的parse()方法,如下:
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
3、UriMatcher、ContentUrist和ContentResolver簡介
因?yàn)閁ri代表了要操作的數(shù)據(jù),所以我們很經(jīng)常需要解析Uri,并從 Uri中獲取數(shù)據(jù)。Android系統(tǒng)提供了兩個(gè)用于操作Uri的工具類,分別為UriMatcher 和ContentUris 。掌握它們的使用,會(huì)便于我們的開發(fā)工作。
UriMatcher:用于匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路徑全部給注冊上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼(-1)。
UriMatcher uriMatcher =
new
UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配[content://com.changcheng.sqlite.provider.contactprovider /contact](content://com.changcheng.sqlite.provider.contactprovider%C2%A0/contact)路徑,返回匹配碼為1
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact”, 1);
//添加需要匹配uri,如果匹配就會(huì)返回匹配碼
//如果match()方法匹配 [content://com.changcheng.sqlite.provider.contactprovider/contact/230](content://com.changcheng.sqlite.provider.contactprovider/contact/230)路徑,返回匹配碼為2
uriMatcher.addURI(“com.changcheng.sqlite.provider.contactprovider”, “contact/#”, 2);
//#號為通配符
2.注冊完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法對輸入的Uri進(jìn)行匹配,如果匹配就返回匹配碼,匹配碼是調(diào)用 addURI()方法傳入的第三個(gè)參數(shù),假設(shè)匹配 content://com.changcheng.sqlite.provider.contactprovider/contact路徑,返回的匹配碼為1。
ContentUris:用于獲取Uri路徑后面的ID部分,它有兩個(gè)比較實(shí)用的方法:
withAppendedId(uri, id)用于為路徑加上ID部分
parseId(uri)方法用于從路徑中獲取ID部分
ContentResolver:當(dāng)外部應(yīng)用需要對ContentProvider中的數(shù)據(jù)進(jìn)行添加、刪除、修改和查詢操作時(shí),可以使用 ContentResolver 類來完成,要獲取ContentResolver 對象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,來操作數(shù)據(jù)。
activity的啟動(dòng)模式有哪些?是什么含義?
在android里,有4種activity的啟動(dòng)模式,分別為:
“standard” (默認(rèn))
“singleTop”
“singleTask”
“singleInstance”
它們主要有如下不同:
1. 如何決定所屬task
“standard”和”singleTop”的activity的目標(biāo)task,和收到的Intent的發(fā)送者在同一個(gè)task內(nèi),除非intent包括參數(shù)FLAG_ACTIVITY_NEW_TASK。
如果提供了FLAG_ACTIVITY_NEW_TASK參數(shù),會(huì)啟動(dòng)到別的task里。
“singleTask”和”singleInstance”總是把a(bǔ)ctivity作為一個(gè)task的根元素,他們不會(huì)被啟動(dòng)到一個(gè)其他task里。
2. 是否允許多個(gè)實(shí)例
“standard”和”singleTop”可以被實(shí)例化多次,并且存在于不同的task中,且一個(gè)task可以包括一個(gè)activity的多個(gè)實(shí)例;
“singleTask”和”singleInstance”則限制只生成一個(gè)實(shí)例,并且是task的根元素。 singleTop要求如果創(chuàng)建intent的時(shí)候棧頂已經(jīng)有要?jiǎng)?chuàng)建的Activity的實(shí)例,則將intent發(fā)送給該實(shí)例,而不發(fā)送給新的實(shí)例。
3. 是否允許其它activity存在于本task內(nèi)
“singleInstance”獨(dú)占一個(gè)task,其它activity不能存在那個(gè)task里;如果它啟動(dòng)了一個(gè)新的activity,不管新的activity的launch mode 如何,新的activity都將會(huì)到別的task里運(yùn)行(如同加了FLAG_ACTIVITY_NEW_TASK參數(shù))。
而另外三種模式,則可以和其它activity共存。
4. 是否每次都生成新實(shí)例
“standard”對于沒一個(gè)啟動(dòng)Intent都會(huì)生成一個(gè)activity的新實(shí)例;
“singleTop”的activity如果在task的棧頂?shù)脑?,則不生成新的該activity的實(shí)例,直接使用棧頂?shù)膶?shí)例,否則,生成該activity的實(shí)例。
比如現(xiàn)在task棧元素為A-B-C-D(D在棧頂),這時(shí)候給D發(fā)一個(gè)啟動(dòng)intent,如果D是 “standard”的,則生成D的一個(gè)新實(shí)例,棧變?yōu)锳-B-C-D-D。
如果D是singleTop的話,則不會(huì)生產(chǎn)D的新實(shí)例,棧狀態(tài)仍為A-B-C-D
如果這時(shí)候給B發(fā)Intent的話,不管B的launchmode是”standard” 還是 “singleTop” ,都會(huì)生成B的新實(shí)例,棧狀態(tài)變?yōu)锳-B-C-D-B。
“singleInstance”是其所在棧的唯一activity,它會(huì)每次都被重用。
“singleTask”如果在棧頂,則接受intent,否則,該intent會(huì)被丟棄,但是該task仍會(huì)回到前臺(tái)。
當(dāng)已經(jīng)存在的activity實(shí)例處理新的intent時(shí)候,會(huì)調(diào)用onNewIntent()方法 如果收到intent生成一個(gè)activity實(shí)例,那么用戶可以通過back鍵回到上一個(gè)狀態(tài);如果是已經(jīng)存在的一個(gè)activity來處理這個(gè)intent的話,用戶不能通過按back鍵返回到這之前的狀態(tài)。
請描述下Activity的生命周期。
activity的生命周期方法有:onCreate()、onStart()、onReStart()、onResume()、onPause()、onStop()、onDestory();
可見生命周期:從onStart()直到系統(tǒng)調(diào)用onStop()
前臺(tái)生命周期:從onResume()直到系統(tǒng)調(diào)用onPause()
如何啟用Service,如何停用Service。
服務(wù)的開發(fā)比較簡單,如下:
第一步:繼承Service類
1
public class SMSService extends Service {}
第二步:在AndroidManifest.xml文件中的<application>節(jié)點(diǎn)里對服務(wù)進(jìn)行配置:<service android:name=".SMSService" />
服務(wù)不能自己運(yùn)行,需要通過調(diào)用Context.startService()或Context.bindService()方法啟動(dòng)服務(wù)。這兩個(gè)方法都可以啟動(dòng)Service,但是它們的使用場合有所不同。使用startService()方法啟用服務(wù),調(diào)用者與服務(wù)之間沒有關(guān)連,即使調(diào)用者退出了,服務(wù)仍然運(yùn)行。使用bindService()方法啟用服務(wù),調(diào)用者與服務(wù)綁定在了一起,調(diào)用者一旦退出,服務(wù)也就終止,大有“不求同時(shí)生,必須同時(shí)死”的特點(diǎn)。
如果打算采用Context.startService()方法啟動(dòng)服務(wù),在服務(wù)未被創(chuàng)建時(shí),系統(tǒng)會(huì)先調(diào)用服務(wù)的onCreate()方法,接著調(diào)用onStart()方法。如果調(diào)用startService()方法前服務(wù)已經(jīng)被創(chuàng)建,多次調(diào)用startService()方法并不會(huì)導(dǎo)致多次創(chuàng)建服務(wù),但會(huì)導(dǎo)致多次調(diào)用onStart()方法。采用startService()方法啟動(dòng)的服務(wù),只能調(diào)用Context.stopService()方法結(jié)束服務(wù),服務(wù)結(jié)束時(shí)會(huì)調(diào)用onDestroy()方法。
如果打算采用Context.bindService()方法啟動(dòng)服務(wù),在服務(wù)未被創(chuàng)建時(shí),系統(tǒng)會(huì)先調(diào)用服務(wù)的onCreate()方法,接著調(diào)用onBind()方法。這個(gè)時(shí)候調(diào)用者和服務(wù)綁定在一起,調(diào)用者退出了,系統(tǒng)就會(huì)先調(diào)用服務(wù)的onUnbind()方法,接著調(diào)用onDestroy()方法。如果調(diào)用bindService()方法前服務(wù)已經(jīng)被綁定,多次調(diào)用bindService()方法并不會(huì)導(dǎo)致多次創(chuàng)建服務(wù)及綁定(也就是說onCreate()和onBind()方法并不會(huì)被多次調(diào)用)。如果調(diào)用者希望與正在綁定的服務(wù)解除綁定,可以調(diào)用unbindService()方法,調(diào)用該方法也會(huì)導(dǎo)致系統(tǒng)調(diào)用服務(wù)的onUnbind()-->onDestroy()方法。
服務(wù)常用生命周期回調(diào)方法如下:
onCreate() 該方法在服務(wù)被創(chuàng)建時(shí)調(diào)用,該方法只會(huì)被調(diào)用一次,無論調(diào)用多少次startService()或bindService()方法,服務(wù)也只被創(chuàng)建一次。
onDestroy()該方法在服務(wù)被終止時(shí)調(diào)用。
與采用Context.startService()方法啟動(dòng)服務(wù)有關(guān)的生命周期方法
onStart() 只有采用Context.startService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在服務(wù)開始運(yùn)行時(shí)被調(diào)用。多次調(diào)用startService()方法盡管不會(huì)多次創(chuàng)建服務(wù),但onStart() 方法會(huì)被多次調(diào)用。
與采用Context.bindService()方法啟動(dòng)服務(wù)有關(guān)的生命周期方法
onBind()只有采用Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在調(diào)用者與服務(wù)綁定時(shí)被調(diào)用,當(dāng)調(diào)用者與服務(wù)已經(jīng)綁定,多次調(diào)用Context.bindService()方法并不會(huì)導(dǎo)致該方法被多次調(diào)用。
onUnbind()只有采用Context.bindService()方法啟動(dòng)服務(wù)時(shí)才會(huì)回調(diào)該方法。該方法在調(diào)用者與服務(wù)解除綁定時(shí)被調(diào)用
注冊廣播有幾種方式,這些方式有何優(yōu)缺點(diǎn)?請談?wù)凙ndroid引入廣播機(jī)制的用意。
首先寫一個(gè)類要繼承BroadcastReceiver
第一種:在清單文件中聲明,添加
<receive android:name=".IncomingSMSReceiver " >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED")
<intent-filter>
<receiver>
第二種使用代碼進(jìn)行注冊如:
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
IncomingSMSReceiver receiver = new IncomgSMSReceiver();
registerReceiver(receiver.filter);
兩種注冊類型的區(qū)別是:
1)第一種不是常駐型廣播,也就是說廣播跟隨程序的生命周期。
2)第二種是常駐型,也就是說當(dāng)應(yīng)用程序關(guān)閉后,如果有信息廣播來,程序也會(huì)被系統(tǒng)調(diào)用自動(dòng)運(yùn)行。
請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關(guān)系。
簡單的說,Handler獲取當(dāng)前線程中的looper對象,looper用來從存放Message的MessageQueue中取出Message,再有Handler進(jìn)行Message的分發(fā)和處理.
Message Queue(消息隊(duì)列):用來存放通過Handler發(fā)布的消息,通常附屬于某一個(gè)創(chuàng)建它的線程,可以通過Looper.myQueue()得到當(dāng)前線程的消息隊(duì)列
Handler:可以發(fā)布或者處理一個(gè)消息或者操作一個(gè)Runnable,通過Handler發(fā)布消息,消息將只會(huì)發(fā)送到與它關(guān)聯(lián)的消息隊(duì)列,然也只能處理該消息隊(duì)列中的消息
Looper:是Handler和消息隊(duì)列之間通訊橋梁,程序組件首先通過Handler把消息傳遞給Looper,Looper把消息放入隊(duì)列。Looper也把消息隊(duì)列里的消息廣播給所有的
Handler:Handler接受到消息后調(diào)用handleMessage進(jìn)行處理
Message:消息的類型,在Handler類中的handleMessage方法中得到單個(gè)的消息進(jìn)行處理
在單線程模型下,為了線程通信問題,Android設(shè)計(jì)了一個(gè)Message Queue(消息隊(duì)列), 線程間可以通過該Message Queue并結(jié)合Handler和Looper組件進(jìn)行信息交換。下面將對它們進(jìn)行分別介紹:
1. Message
Message消息,理解為線程間交流的信息,處理數(shù)據(jù)后臺(tái)線程需要更新UI,則發(fā)送Message內(nèi)含一些數(shù)據(jù)給UI線程。
2. Handler
Handler處理者,是Message的主要處理者,負(fù)責(zé)Message的發(fā)送,Message內(nèi)容的執(zhí)行處理。后臺(tái)線程就是通過傳進(jìn)來的 Handler對象引用來sendMessage(Message)。而使用Handler,需要implement 該類的 handleMessage(Message)方法,它是處理這些Message的操作內(nèi)容,例如Update UI。通常需要子類化Handler來實(shí)現(xiàn)handleMessage方法。
3. Message Queue
Message Queue消息隊(duì)列,用來存放通過Handler發(fā)布的消息,按照先進(jìn)先出執(zhí)行。
每個(gè)message queue都會(huì)有一個(gè)對應(yīng)的Handler。Handler會(huì)向message queue通過兩種方法發(fā)送消息:sendMessage或post。這兩種消息都會(huì)插在message queue隊(duì)尾并按先進(jìn)先出執(zhí)行。但通過這兩種方法發(fā)送的消息執(zhí)行的方式略有不同:通過sendMessage發(fā)送的是一個(gè)message對象,會(huì)被 Handler的handleMessage()函數(shù)處理;而通過post方法發(fā)送的是一個(gè)runnable對象,則會(huì)自己執(zhí)行。
4. Looper
Looper是每條線程里的Message Queue的管家。Android沒有Global的Message Queue,而Android會(huì)自動(dòng)替主線程(UI線程)建立Message Queue,但在子線程里并沒有建立Message Queue。所以調(diào)用Looper.getMainLooper()得到的主線程的Looper不為NULL,但調(diào)用Looper.myLooper() 得到當(dāng)前線程的Looper就有可能為NULL。對于子線程使用Looper,API Doc提供了正確的使用方法:這個(gè)Message機(jī)制的大概流程:
1. 在Looper.loop()方法運(yùn)行開始后,循環(huán)地按照接收順序取出Message Queue里面的非NULL的Message。
2. 一開始Message Queue里面的Message都是NULL的。當(dāng)Handler.sendMessage(Message)到Message Queue,該函數(shù)里面設(shè)置了那個(gè)Message對象的target屬性是當(dāng)前的Handler對象。隨后Looper取出了那個(gè)Message,則調(diào)用 該Message的target指向的Hander的dispatchMessage函數(shù)對Message進(jìn)行處理。在dispatchMessage方法里,如何處理Message則由用戶指定,三個(gè)判斷,優(yōu)先級從高到低:
1) Message里面的Callback,一個(gè)實(shí)現(xiàn)了Runnable接口的對象,其中run函數(shù)做處理工作;
2) Handler里面的mCallback指向的一個(gè)實(shí)現(xiàn)了Callback接口的對象,由其handleMessage進(jìn)行處理;
3) 處理消息Handler對象對應(yīng)的類繼承并實(shí)現(xiàn)了其中handleMessage函數(shù),通過這個(gè)實(shí)現(xiàn)的handleMessage函數(shù)處理消息。
由此可見,我們實(shí)現(xiàn)的handleMessage方法是優(yōu)先級最低的!
3. Handler處理完該Message (update UI) 后,Looper則設(shè)置該Message為NULL,以便回收!
在網(wǎng)上有很多文章講述主線程和其他子線程如何交互,傳送信息,最終誰來執(zhí)行處理信息之類的,個(gè)人理解是最簡單的方法——判斷Handler對象里面的Looper對象是屬于哪條線程的,則由該線程來執(zhí)行!
1. 當(dāng)Handler對象的構(gòu)造函數(shù)的參數(shù)為空,則為當(dāng)前所在線程的Looper;
2. Looper.getMainLooper()得到的是主線程的Looper對象,Looper.myLooper()得到的是當(dāng)前線程的Looper對象。
簡要解釋一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver
一個(gè)activity呈現(xiàn)了一個(gè)用戶可以操作的可視化用戶界面;一個(gè)service不包含可見的用戶界面,而是在后臺(tái)運(yùn)行,可以與一個(gè)activity綁定,通過綁定暴露出來接口并與其進(jìn)行通信;一個(gè)broadcast receiver是一個(gè)接收廣播消息并做出回應(yīng)的component,broadcast receiver沒有界面;一個(gè)intent是一個(gè)Intent對象,它保存了消息的內(nèi)容。對于activity和service來說,它指定了請求的操作名稱和待操作數(shù)據(jù)的URI,Intent對象可以顯式的指定一個(gè)目標(biāo)component。如果這樣的話,android會(huì)找到這個(gè)component(基于manifest文件中的聲明)并激活它。但如果一個(gè)目標(biāo)不是顯式指定的,android必須找到響應(yīng)intent的最佳component。它是通過將Intent對象和目標(biāo)的intent filter相比較來完成這一工作的;一個(gè)component的intent filter告訴android該component能處理的intent。intent filter也是在manifest文件中聲明的。
什么是ANR 如何避免它?
ANR:Application Not Responding。在Android中,活動(dòng)管理器和窗口管理器這兩個(gè)系統(tǒng)服務(wù)負(fù)責(zé)監(jiān)視應(yīng)用程序的響應(yīng),當(dāng)用戶操作的在5s內(nèi)應(yīng)用程序沒能做出反應(yīng),BroadcastReceiver在10秒內(nèi)沒有執(zhí)行完畢,就會(huì)出現(xiàn)應(yīng)用程序無響應(yīng)對話框,這既是ANR。
避免方法:Activity應(yīng)該在它的關(guān)鍵生命周期方法(如onCreate()和onResume())里盡可能少的去做創(chuàng)建操作。潛在的耗時(shí)操作,例如網(wǎng)絡(luò)或數(shù)據(jù)庫操作,或者高耗時(shí)的計(jì)算如改變位圖尺寸,應(yīng)該在子線程里(或者異步方式)來完成。主線程應(yīng)該為子線程提供一個(gè)Handler,以便完成時(shí)能夠提交給主線程。
什么情況會(huì)導(dǎo)致Force Close ?如何避免?能否捕獲導(dǎo)致其的異常?
程序出現(xiàn)異常,比如nullpointer。
避免:編寫程序時(shí)邏輯連貫,思維縝密。能捕獲異常,在logcat中能看到異常信息
描述一下android的系統(tǒng)架構(gòu)
android系統(tǒng)架構(gòu)分從下往上為linux 內(nèi)核層、運(yùn)行庫、應(yīng)用程序框架層、和應(yīng)用程序?qū)印?
linuxkernel:負(fù)責(zé)硬件的驅(qū)動(dòng)程序、網(wǎng)絡(luò)、電源、系統(tǒng)安全以及內(nèi)存管理等功能。
libraries和 android runtime:libraries:即c/c++函數(shù)庫部分,大多數(shù)都是開放源代碼的函數(shù)庫,例如webkit(引擎),該函數(shù)庫負(fù)責(zé) android網(wǎng)頁瀏覽器的運(yùn)行,例如標(biāo)準(zhǔn)的c函數(shù)庫libc、openssl、sqlite等,當(dāng)然也包括支持游戲開發(fā)2dsgl和 3dopengles,在多媒體方面有mediaframework框架來支持各種影音和圖形文件的播放與顯示,例如mpeg4、h.264、mp3、 aac、amr、jpg和png等眾多的多媒體文件格式。android的runtime負(fù)責(zé)解釋和執(zhí)行生成的dalvik格式的字節(jié)碼。
applicationframework(應(yīng)用軟件架構(gòu)),java應(yīng)用程序開發(fā)人員主要是使用該層封裝好的api進(jìn)行快速開發(fā)。
applications:該層是java的應(yīng)用程序?qū)?,android內(nèi)置的googlemaps、e-mail、即時(shí)通信工具、瀏覽器、mp3播放器等處于該層,java開發(fā)人員開發(fā)的程序也處于該層,而且和內(nèi)置的應(yīng)用程序具有平等的位置,可以調(diào)用內(nèi)置的應(yīng)用程序,也可以替換內(nèi)置的應(yīng)用程序。
上面的四個(gè)層次,下層為上層服務(wù),上層需要下層的支持,調(diào)用下層的服務(wù),這種嚴(yán)格分層的方式帶來的極大的穩(wěn)定性、靈活性和可擴(kuò)展性,使得不同層的開發(fā)人員可以按照規(guī)范專心特定層的開發(fā)。
android應(yīng)用程序使用框架的api并在框架下運(yùn)行,這就帶來了程序開發(fā)的高度一致性,另一方面也告訴我們,要想寫出優(yōu)質(zhì)高效的程序就必須對整個(gè) applicationframework進(jìn)行非常深入的理解。精通applicationframework,你就可以真正的理解android的設(shè)計(jì)和運(yùn)行機(jī)制,也就更能夠駕馭整個(gè)應(yīng)用層的開發(fā)。
請介紹下ContentProvider是如何實(shí)現(xiàn)數(shù)據(jù)共享的
一個(gè)程序可以通過實(shí)現(xiàn)一個(gè)Content provider的抽象接口將自己的數(shù)據(jù)完全暴露出去,而且Content providers是以類似數(shù)據(jù)庫中表的方式將數(shù)據(jù)暴露。Content providers存儲(chǔ)和檢索數(shù)據(jù),通過它可以讓所有的應(yīng)用程序訪問到,這也是應(yīng)用程序之間唯一共享數(shù)據(jù)的方法。
要想使應(yīng)用程序的數(shù)據(jù)公開化,可通過2種方法:創(chuàng)建一個(gè)屬于你自己的Content provider或者將你的數(shù)據(jù)添加到一個(gè)已經(jīng)存在的Content provider中,前提是有相同數(shù)據(jù)類型并且有寫入Content provider的權(quán)限。
如何通過一套標(biāo)準(zhǔn)及統(tǒng)一的接口獲取其他應(yīng)用程序暴露的數(shù)據(jù)?
Android提供了ContentResolver,外界的程序可以通過ContentResolver接口訪問ContentProvider提供的數(shù)據(jù)。
Service和Thread的區(qū)別?
答:servie是系統(tǒng)的組件,它由系統(tǒng)進(jìn)程托管(servicemanager);它們之間的通信類似于client和server,是一種輕量級的ipc通信,這種通信的載體是binder,它是在linux層交換信息的一種ipc。而thread是由本應(yīng)用程序托管。1). Thread:Thread 是程序執(zhí)行的最小單元,它是分配CPU的基本單位??梢杂?Thread 來執(zhí)行一些異步的操作。
2). Service:Service 是android的一種機(jī)制,當(dāng)它運(yùn)行的時(shí)候如果是Local Service,那么對應(yīng)的 Service 是運(yùn)行在主進(jìn)程的 main 線程上的。如:onCreate,onStart 這些函數(shù)在被系統(tǒng)調(diào)用的時(shí)候都是在主進(jìn)程的 main 線程上運(yùn)行的。如果是Remote Service,那么對應(yīng)的 Service 則是運(yùn)行在獨(dú)立進(jìn)程的 main 線程上。
既然這樣,那么我們?yōu)槭裁匆?Service 呢?其實(shí)這跟 android 的系統(tǒng)機(jī)制有關(guān),我們先拿 Thread 來說。Thread 的運(yùn)行是獨(dú)立于 Activity 的,也就是說當(dāng)一個(gè) Activity 被 finish 之后,如果你沒有主動(dòng)停止 Thread 或者 Thread 里的 run 方法沒有執(zhí)行完畢的話,Thread 也會(huì)一直執(zhí)行。因此這里會(huì)出現(xiàn)一個(gè)問題:當(dāng) Activity 被 finish 之后,你不再持有該 Thread 的引用。另一方面,你沒有辦法在不同的 Activity 中對同一 Thread 進(jìn)行控制。
舉個(gè)例子:如果你的 Thread 需要不停地隔一段時(shí)間就要連接服務(wù)器做某種同步的話,該 Thread 需要在 Activity 沒有start的時(shí)候也在運(yùn)行。這個(gè)時(shí)候當(dāng)你 start 一個(gè) Activity 就沒有辦法在該 Activity 里面控制之前創(chuàng)建的 Thread。因此你便需要?jiǎng)?chuàng)建并啟動(dòng)一個(gè) Service ,在 Service 里面創(chuàng)建、運(yùn)行并控制該 Thread,這樣便解決了該問題(因?yàn)槿魏?Activity 都可以控制同一 Service,而系統(tǒng)也只會(huì)創(chuàng)建一個(gè)對應(yīng) Service 的實(shí)例)。
因此你可以把 Service 想象成一種消息服務(wù),而你可以在任何有 Context 的地方調(diào)用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,來控制它,你也可以在 Service 里注冊 BroadcastReceiver,在其他地方通過發(fā)送 broadcast 來控制它,當(dāng)然這些都是 Thread 做不到的。
Android本身的api并未聲明會(huì)拋出異常,則其在運(yùn)行時(shí)有無可能拋出runtime異常,你遇到過嗎?諾有的話會(huì)導(dǎo)致什么問題?如何解決?
會(huì),比如nullpointerException。我遇到過,比如textview.setText()時(shí),textview沒有初始化。會(huì)導(dǎo)致程序無法正常運(yùn)行出現(xiàn)forceclose。打開控制臺(tái)查看logcat信息找出異常信息并修改程序
IntentService有何優(yōu)點(diǎn)?
Acitivity的進(jìn)程,當(dāng)處理Intent的時(shí)候,會(huì)產(chǎn)生一個(gè)對應(yīng)的Service; Android的進(jìn)程處理器現(xiàn)在會(huì)盡可能的不kill掉你;非常容易使用
如果后臺(tái)的Activity由于某原因被系統(tǒng)回收了,如何在被系統(tǒng)回收之前保存當(dāng)前狀態(tài)?
重寫onSaveInstanceState()方法,在此方法中保存需要保存的數(shù)據(jù),該方法將會(huì)在activity被回收之前調(diào)用。通過重寫onRestoreInstanceState()方法可以從中提取保存好的數(shù)據(jù)
如何將一個(gè)Activity設(shè)置成窗口的樣式。
<activity>中配置:android :theme="@android:style/Theme.Dialog"
另外android:theme="@android:style/Theme.Translucent" 是設(shè)置透明
如何退出Activity?如何安全退出已調(diào)用多個(gè)Activity的Application?
對于單一Activity的應(yīng)用來說,退出很簡單,直接finish()即可。當(dāng)然,也可以用killProcess()和System.exit()這樣的方法。
對于多個(gè)activity,1、記錄打開的Activity:每打開一個(gè)Activity,就記錄下來。在需要退出時(shí),關(guān)閉每一個(gè)Activity即可。2、發(fā)送特定廣播:在需要結(jié)束應(yīng)用時(shí),發(fā)送一個(gè)特定的廣播,每個(gè)Activity收到廣播后,關(guān)閉即可。3、遞歸退出:在打開新的Activity時(shí)使用startActivityForResult,然后自己加標(biāo)志,在onActivityResult中處理,遞歸關(guān)閉。為了編程方便,最好定義一個(gè)Activity基類,處理這些共通問題。
現(xiàn)提供幾個(gè)方法,供參考:
1、拋異常強(qiáng)制退出:
該方法通過拋異常,使程序Force Close。
驗(yàn)證可以,但是,需要解決的問題是,如何使程序結(jié)束掉,而不彈出Force Close的窗口。
2、記錄打開的Activity:
每打開一個(gè)Activity,就記錄下來。在需要退出時(shí),關(guān)閉每一個(gè)Activity即可。
3、發(fā)送特定廣播:
在需要結(jié)束應(yīng)用時(shí),發(fā)送一個(gè)特定的廣播,每個(gè)Activity收到廣播后,關(guān)閉即可。
4、遞歸退出
在打開新的Activity時(shí)使用startActivityForResult,然后自己加標(biāo)志,在onActivityResult中處理,遞歸關(guān)閉。
除了第一個(gè),都是想辦法把每一個(gè)Activity都結(jié)束掉,間接達(dá)到目的。但是這樣做同樣不完美。你會(huì)發(fā)現(xiàn),如果自己的應(yīng)用程序?qū)γ恳粋€(gè)Activity都設(shè)置了nosensor,在兩個(gè)Activity結(jié)束的間隙,sensor可能有效了。但至少,我們的目的達(dá)到了,而且沒有影響用戶使用。為了編程方便,最好定義一個(gè)Activity基類,處理這些共通問題。
AIDL的全稱是什么?如何工作?能處理哪些類型的數(shù)據(jù)?
全稱是:Android Interface Define Language
在Android中, 每個(gè)應(yīng)用程序都可以有自己的進(jìn)程. 在寫UI應(yīng)用的時(shí)候, 經(jīng)常要用到Service. 在不同的進(jìn)程中, 怎樣傳遞對象呢?顯然, Java中不允許跨進(jìn)程內(nèi)存共享. 因此傳遞對象, 只能把對象拆分成操作系統(tǒng)能理解的簡單形式, 以達(dá)到跨界對象訪問的目的. 在J2EE中,采用RMI的方式, 可以通過序列化傳遞對象. 在Android中, 則采用AIDL的方式. 理論上AIDL可以傳遞Bundle,實(shí)際上做起來卻比較麻煩。
AIDL(AndRoid接口描述語言)是一種借口描述語言; 編譯器可以通過aidl文件生成一段代碼,通過預(yù)先定義的接口達(dá)到兩個(gè)進(jìn)程內(nèi)部通信進(jìn)程的目的. 如果需要在一個(gè)Activity中, 訪問另一個(gè)Service中的某個(gè)對象, 需要先將對象轉(zhuǎn)化成AIDL可識(shí)別的參數(shù)(可能是多個(gè)參數(shù)), 然后使用AIDL來傳遞這些參數(shù), 在消息的接收端, 使用這些參數(shù)組裝成自己需要的對象.
AIDL的IPC的機(jī)制和COM或CORBA類似, 是基于接口的,但它是輕量級的。它使用代理類在客戶端和實(shí)現(xiàn)層間傳遞值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相關(guān)類.; 2. 調(diào)用aidl產(chǎn)生的class.
AIDL的創(chuàng)建方法:
AIDL語法很簡單,可以用來聲明一個(gè)帶一個(gè)或多個(gè)方法的接口,也可以傳遞參數(shù)和返回值。 由于遠(yuǎn)程調(diào)用的需要, 這些參數(shù)和返回值并不是任何類型.下面是些AIDL支持的數(shù)據(jù)類型:
1. 不需要import聲明的簡單Java編程語言類型(int,boolean等)
2. String, CharSequence不需要特殊聲明
3. List, Map和Parcelables類型, 這些類型內(nèi)所包含的數(shù)據(jù)成員也只能是簡單數(shù)據(jù)類型, String等其他比支持的類型.
(另外: 我沒嘗試Parcelables, 在Eclipse+ADT下編譯不過, 或許以后會(huì)有所支持)
請解釋下Android程序運(yùn)行時(shí)權(quán)限與文件系統(tǒng)權(quán)限的區(qū)別
運(yùn)行時(shí)權(quán)限D(zhuǎn)alvik( android授權(quán))
文件系統(tǒng) linux 內(nèi)核授權(quán)
系統(tǒng)上安裝了多種瀏覽器,能否指定某瀏覽器訪問指定頁面?請說明原由。
通過直接發(fā)送Uri把參數(shù)帶過去,或者通過manifest里的intentfilter里的data屬性
android系統(tǒng)的優(yōu)勢和不足
Android平臺(tái)手機(jī) 5大優(yōu)勢:
一、開放性
在優(yōu)勢方面,Android平臺(tái)首先就是其開發(fā)性,開發(fā)的平臺(tái)允許任何移動(dòng)終端廠商加入到Android聯(lián)盟中來。顯著的開放性可以使其擁有更多的開發(fā)者,隨著用戶和應(yīng)用的日益豐富,一個(gè)嶄新的平臺(tái)也將很快走向成熟。開放性對于Android的發(fā)展而言,有利于積累人氣,這里的人氣包括消費(fèi)者和廠商,而對于消費(fèi)者來講,隨大的受益正是豐富的軟件資源。開放的平臺(tái)也會(huì)帶來更大競爭,如此一來,消費(fèi)者將可以用更低的價(jià)位購得心儀的手機(jī)。
二、掙脫運(yùn)營商的束縛
在過去很長的一段時(shí)間,特別是在歐美地區(qū),手機(jī)應(yīng)用往往受到運(yùn)營商制約,使用什么功能接入什么網(wǎng)絡(luò),幾乎都受到運(yùn)營商的控制。從去年iPhone 上市 ,用戶可以更加方便地連接網(wǎng)絡(luò),運(yùn)營商的制約減少。隨著EDGE、HSDPA這些2G至3G移動(dòng)網(wǎng)絡(luò)的逐步過渡和提升,手機(jī)隨意接入網(wǎng)絡(luò)已不是運(yùn)營商口中的笑談,當(dāng)你可以通過手機(jī)IM軟件方便地進(jìn)行即時(shí)聊天時(shí),再回想不久前天價(jià)的彩信和圖鈴下載業(yè)務(wù),是不是像噩夢一樣?互聯(lián)網(wǎng)巨頭Google推動(dòng)的Android終端天生就有網(wǎng)絡(luò)特色,將讓用戶離互聯(lián)網(wǎng)更近。
三、豐富的硬件選擇
這一點(diǎn)還是與Android平臺(tái)的開放性相關(guān),由于Android的開放性,眾多的廠商會(huì)推出千奇百怪,功能特色各具的多種產(chǎn)品。功能上的差異和特色,卻不會(huì)影響到數(shù)據(jù)同步、甚至軟件的兼容,好比你從諾基亞 Symbian風(fēng)格手機(jī) 一下改用蘋果 iPhone ,同時(shí)還可將Symbian中優(yōu)秀的軟件帶到iPhone上使用、聯(lián)系人等資料更是可以方便地轉(zhuǎn)移,是不是非常方便呢?
四、不受任何限制的開發(fā)商
Android平臺(tái)提供給第三方開發(fā)商一個(gè)十分寬泛、自由的環(huán)境,不會(huì)受到各種條條框框的阻擾,可想而知,會(huì)有多少新穎別致的軟件會(huì)誕生。但也有其兩面性,血腥、暴力、情色方面的程序和游戲如可控制正是留給Android難題之一。
五、無縫結(jié)合的Google應(yīng)用
如今叱詫互聯(lián)網(wǎng)的Google已經(jīng)走過10年度歷史,從搜索巨人到全面的互聯(lián)網(wǎng)滲透,Google服務(wù)如地圖、郵件、搜索等已經(jīng)成為連接用戶和互聯(lián)網(wǎng)的重要紐帶,而Android平臺(tái)手機(jī)將無縫結(jié)合這些優(yōu)秀的Google服務(wù)。
再說Android的5大不足:
一、安全和隱私
由于手機(jī) 與互聯(lián)網(wǎng)的緊密聯(lián)系,個(gè)人隱私很難得到保守。除了上網(wǎng)過程中經(jīng)意或不經(jīng)意留下的個(gè)人足跡,Google這個(gè)巨人也時(shí)時(shí)站在你的身后,洞穿一切,因此,互聯(lián)網(wǎng)的深入將會(huì)帶來新一輪的隱私危機(jī)。
二、首先開賣Android手機(jī)的不是最大運(yùn)營商
眾所周知,T-Mobile在23日,于美國紐約發(fā)布 了Android首款手機(jī)G1。但是在北美市場,最大的兩家運(yùn)營商乃AT&T和Verizon,而目前所知取得Android手機(jī)銷售權(quán)的僅有 T-Mobile和Sprint,其中T-Mobile的3G網(wǎng)絡(luò)相對于其他三家也要遜色不少,因此,用戶可以買賬購買G1,能否體驗(yàn)到最佳的3G網(wǎng)絡(luò)服務(wù)則要另當(dāng)別論了!
三、運(yùn)營商仍然能夠影響到Android手機(jī)
在國內(nèi)市場,不少用戶對購得移動(dòng)定制機(jī)不滿,感覺所購的手機(jī)被人涂畫了廣告一般。這樣的情況在國外市場同樣出現(xiàn)。Android手機(jī)的另一發(fā)售運(yùn)營商Sprint就將在其機(jī)型中內(nèi)置其手機(jī)商店程序。
四、同類機(jī)型用戶減少
在不少手機(jī)論壇都會(huì)有針對某一型號的子論壇,對一款手機(jī)的使用心得交流,并分享軟件資源。而對于Android平臺(tái)手機(jī),由于廠商豐富,產(chǎn)品類型多樣,這樣使用同一款機(jī)型的用戶越來越少,缺少統(tǒng)一機(jī)型的程序強(qiáng)化。舉個(gè)稍顯不當(dāng)?shù)睦樱F(xiàn)在山寨機(jī)泛濫,品種各異,就很少有專門針對某個(gè)型號山寨機(jī)的討論和群組,除了哪些功能異常搶眼、頗受追捧的機(jī)型以外。
五、過分依賴開發(fā)商缺少標(biāo)準(zhǔn)配置
在使用PC端的Windows Xp系統(tǒng)的時(shí)候,都會(huì)內(nèi)置微軟Windows Media Player這樣一個(gè)瀏覽器程序,用戶可以選擇更多樣的播放器,如Realplay或暴風(fēng)影音等。但入手開始使用默認(rèn)的程序同樣可以應(yīng)付多樣的需要。在 Android平臺(tái)中,由于其開放性,軟件更多依賴第三方廠商,比如Android系統(tǒng)的SDK中就沒有內(nèi)置音樂 播放器,全部依賴第三方開發(fā),缺少了產(chǎn)品的統(tǒng)一性。
Android dvm的進(jìn)程和Linux的進(jìn)程, 應(yīng)用程序的進(jìn)程是否為同一個(gè)概念
DVM指dalivk的虛擬機(jī)。每一個(gè)Android應(yīng)用程序都在它自己的進(jìn)程中運(yùn)行,都擁有一個(gè)獨(dú)立的Dalvik虛擬機(jī)實(shí)例。而每一個(gè)DVM都是在Linux 中的一個(gè)進(jìn)程,所以說可以認(rèn)為是同一個(gè)概念。
sim卡的EF文件是什么?有何作用
sim卡的文件系統(tǒng)有自己規(guī)范,主要是為了和手機(jī)通訊,sim本 身可以有自己的操作系統(tǒng),EF就是作存儲(chǔ)并和手機(jī)通訊用的
嵌入式操作系統(tǒng)內(nèi)存管理有哪幾種, 各有何特性
頁式,段式,段頁,用到了MMU,虛擬空間等技術(shù)
什么是嵌入式實(shí)時(shí)操作系統(tǒng), Android 操作系統(tǒng)屬于實(shí)時(shí)操作系統(tǒng)嗎?
嵌入式實(shí)時(shí)操作系統(tǒng)是指當(dāng)外界事件或數(shù)據(jù)產(chǎn)生時(shí),能夠接受并以足夠快的速度予以處理,其處理的結(jié)果又能在規(guī)定的時(shí)間之內(nèi)來控制生產(chǎn)過程或?qū)μ幚硐到y(tǒng)作出快速響應(yīng),并控制所有實(shí)時(shí)任務(wù)協(xié)調(diào)一致運(yùn)行的嵌入式操作系統(tǒng)。主要用于工業(yè)控制、 軍事設(shè)備、 航空航天等領(lǐng)域?qū)ο到y(tǒng)的響應(yīng)時(shí)間有苛刻的要求,這就需要使用實(shí)時(shí)系統(tǒng)。又可分為軟實(shí)時(shí)和硬實(shí)時(shí)兩種,而android是基于linux內(nèi)核的,因此屬于軟實(shí)時(shí)。
一條最長的短信息約占多少byte?
中文70(包括標(biāo)點(diǎn)),英文160,160個(gè)字節(jié)。
如何將SQLite數(shù)據(jù)庫(dictionary.db文件)與apk文件一起發(fā)布
可以將dictionary.db文件復(fù)制到Eclipse Android工程中的res aw目錄中。所有在res aw目錄中的文件不會(huì)被壓縮,這樣可以直接提取該目錄中的文件??梢詫ictionary.db文件復(fù)制到res aw目錄中
如何將打開res aw目錄中的數(shù)據(jù)庫文件?
在Android中不能直接打開res aw目錄中的數(shù)據(jù)庫文件,而需要在程序第一次啟動(dòng)時(shí)將該文件復(fù)制到手機(jī)內(nèi)存或SD卡的某個(gè)目錄中,然后再打開該數(shù)據(jù)庫文件。
復(fù)制的基本方法是使用getResources().openRawResource方法獲得res aw目錄中資源的 InputStream對象,然后將該InputStream對象中的數(shù)據(jù)寫入其他的目錄中相應(yīng)文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法來打開任意目錄中的SQLite數(shù)據(jù)庫文件。
DDMS和TraceView的區(qū)別?
DDMS是一個(gè)程序執(zhí)行查看器,在里面可以看見線程和堆棧等信息,TraceView是程序性能分析器 。
java中如何引用本地語言
可以用JNI(java native interface java 本地接口)接口 。
談?wù)凙ndroid的IPC(進(jìn)程間通信)機(jī)制
IPC是內(nèi)部進(jìn)程通信的簡稱, 是共享"命名管道"的資源。Android中的IPC機(jī)制是為了讓Activity和Service之間可以隨時(shí)的進(jìn)行交互,故在Android中該機(jī)制,只適用于Activity和Service之間的通信,類似于遠(yuǎn)程方法調(diào)用,類似于C/S模式的訪問。通過定義AIDL接口文件來定義IPC接口。Servier端實(shí)現(xiàn)IPC接口,Client端調(diào)用IPC接口本地代理。
NDK是什么
NDK是一些列工具的集合,NDK提供了一系列的工具,幫助開發(fā)者迅速的開發(fā)C/C++的動(dòng)態(tài)庫,并能自動(dòng)將so和java 應(yīng)用打成apk包。
NDK集成了交叉編譯器,并提供了相應(yīng)的mk文件和隔離cpu、平臺(tái)等的差異,開發(fā)人員只需簡單的修改mk文件就可以創(chuàng)建出so
什么情況下會(huì)導(dǎo)致內(nèi)存泄露
內(nèi)存泄露是個(gè)折騰的問題。
什么時(shí)候會(huì)發(fā)生內(nèi)存泄露?內(nèi)存泄露的根本原因:長生命周期的對象持有短生命周期的對象。短周期對象就無法及時(shí)釋放。
I. 靜態(tài)集合類引起內(nèi)存泄露
主要是hashmap,Vector等,如果是靜態(tài)集合 這些集合沒有及時(shí)setnull的話,就會(huì)一直持有這些對象。
II.remove 方法無法刪除set集 Objects.hash(firstName, lastName);
經(jīng)過測試,hashcode修改后,就沒有辦法remove了。
III. observer 我們在使用監(jiān)聽器的時(shí)候,往往是addxxxlistener,但是當(dāng)我們不需要的時(shí)候,忘記removexxxlistener,就容易內(nèi)存leak。
廣播沒有unregisterrecevier
IV.各種數(shù)據(jù)鏈接沒有關(guān)閉,數(shù)據(jù)庫contentprovider,io,sokect等。cursor
V.內(nèi)部類:
java中的內(nèi)部類(匿名內(nèi)部類),會(huì)持有宿主類的強(qiáng)引用this。
所以如果是new Thread這種,后臺(tái)線程的操作,當(dāng)線程沒有執(zhí)行結(jié)束時(shí),activity不會(huì)被回收。
Context的引用,當(dāng)TextView 等等都會(huì)持有上下文的引用。如果有static drawable,就會(huì)導(dǎo)致該內(nèi)存無法釋放。
VI.單例
單例 是一個(gè)全局的靜態(tài)對象,當(dāng)持有某個(gè)復(fù)制的類A是,A無法被釋放,內(nèi)存leak。
如何避免 OOM 異常
減少內(nèi)存對象的占用
I.ArrayMap/SparseArray代替hashmap
II.避免在android里面使用Enum
III.減少bitmap的內(nèi)存占用
inSampleSize:縮放比例,在把圖片載入內(nèi)存之前,我們需要先計(jì)算出一個(gè)合適的縮放比例,避免不必要的大圖載入。
decode format:解碼格式,選擇ARGB_8888/RBG_565/ARGB_4444/ALPHA_8,存在很大差異。
IV.減少資源圖片的大小,過大的圖片可以考慮分段加載
內(nèi)存對象的重復(fù)利用
大多數(shù)對象的復(fù)用,都是利用對象池的技術(shù)。
I.listview/gridview/recycleview contentview的復(fù)用
II.inBitmap 屬性對于內(nèi)存對象的復(fù)用ARGB_8888/RBG_565/ARGB_4444/ALPHA_8
這個(gè)方法在某些條件下非常有用,比如要加載上千張圖片的時(shí)候。
III.避免在ondraw方法里面 new對象
IV.StringBuilder 代替+
Android 中如何捕獲未捕獲的異常
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static CrashHandler instance = null;
public static synchronized CrashHandler getInstance()
{
if(instance == null)
{
instance = new CrashHandler();
}
return instance;
}
public void init(Context context)
{
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Thread:");
stringBuilder.append(thread.toString());
stringBuilder.append("\t");
stringBuilder.append(ex);
TraceLog.i(stringBuilder.toString());
TraceLog.printCallStatck(ex);
}
}
關(guān)鍵是實(shí)現(xiàn)Thread.UncaughtExceptionHandler
然后是在application的oncreate里面注冊。
ANR 是什么?怎樣避免和解決 ANR(重要)
ANR->Application Not Responding
也就是在規(guī)定的時(shí)間內(nèi),沒有響應(yīng)。
三種類型:
1). KeyDispatchTimeout(5 seconds) --主要類型按鍵或觸摸事件在特定時(shí)間內(nèi)無響應(yīng)
2). BroadcastTimeout(10 seconds) --BroadcastReceiver在特定時(shí)間內(nèi)無法處理完成
3). ServiceTimeout(20 seconds) --小概率類型 Service在特定的時(shí)間內(nèi)無法處理完成
為什么會(huì)超時(shí):事件沒有機(jī)會(huì)處理 & 事件處理超時(shí)
怎么避免ANR
ANR的關(guān)鍵
是處理超時(shí),所以應(yīng)該避免在UI線程,BroadcastReceiver 還有service主線程中,處理復(fù)雜的邏輯和計(jì)算
而交給work thread操作。
1)避免在activity里面做耗時(shí)操作,oncreate & onresume
2)避免在onReceiver里面做過多操作
3)避免在Intent Receiver里啟動(dòng)一個(gè)Activity,因?yàn)樗鼤?huì)創(chuàng)建一個(gè)新的畫面,并從當(dāng)前用戶正在運(yùn)行的程序上搶奪焦點(diǎn)。
4)盡量使用handler來處理UI thread & workthread的交互。
Android 線程間通信有哪幾種方式
1)共享變量(內(nèi)存)
2)管道
3)handle機(jī)制
runOnUiThread(Runnable)
view.post(Runnable)
簡述 android 應(yīng)用程序結(jié)構(gòu)是哪些
1)main code
2) unit test
3)mianifest
4)res->drawable,drawable-xxhdpi,layout,value,mipmap
mipmap 是一種很早就有的技術(shù)了,翻譯過來就是紋理映射技術(shù).
google建議只把啟動(dòng)圖片放入。
5)lib
6)color
Android 程序運(yùn)行時(shí)權(quán)限與文件系統(tǒng)權(quán)限的區(qū)別
文件的系統(tǒng)權(quán)限是由linux系統(tǒng)規(guī)定的,只讀,讀寫等。
運(yùn)行時(shí)權(quán)限,是對于某個(gè)系統(tǒng)上的app的訪問權(quán)限,允許,拒絕,詢問。該功能可以防止非法的程序訪問敏感的信息。
Framework 工作方式及原理,Activity 是如何生成一個(gè) view 的,機(jī)制是什么
Framework是android 系統(tǒng)對 linux kernel,lib庫等封裝,提供WMS,AMS,bind機(jī)制,handler-message機(jī)制等方式,供app使用。
簡單來說framework就是提供app生存的環(huán)境。
1)Activity在attch方法的時(shí)候,會(huì)創(chuàng)建一個(gè)phonewindow(window的子類)
2)onCreate中的setContentView方法,會(huì)創(chuàng)建DecorView
3)DecorView 的addview方法,會(huì)把layout中的布局加載進(jìn)來。
多線程間通信和多進(jìn)程之間通信有什么不同,分別怎么實(shí)現(xiàn)
線程間的通信可以參考第6點(diǎn)。
進(jìn)程間的通信:bind機(jī)制(IPC->AIDL),linux級共享內(nèi)存,boradcast,
Activity 之間,activity & serview之間的通信,無論他們是否在一個(gè)進(jìn)程內(nèi)。
Android 屏幕適配
屏幕適配的方式:xxxdpi, wrap_content,match_parent. 獲取屏幕大小,做處理。
dp來適配屏幕,sp來確定字體大小
drawable-xxdpi, values-1280*1920等 這些就是資源的適配。
wrap_content,match_parent, 這些是view的自適應(yīng)
weight,這是權(quán)重的適配。
什么是 AIDL 以及如何使用
Android Interface Definition Language
AIDL是使用bind機(jī)制來工作。
參數(shù):
java原生參數(shù)
String
parcelable
list & map 元素 需要支持AIDL
Handler 機(jī)制
http://www.cnblogs.com/deman/p/4688054.html
事件分發(fā)機(jī)制
http://www.cnblogs.com/deman/p/5812570.html
子線程發(fā)消息到主線程進(jìn)行更新 UI,除了 handler 和 AsyncTask,還有什么
EventBus,廣播,view.post, runinUiThread
但是無論各種花樣,本質(zhì)上就2種:handler機(jī)制 + 廣播
子線程中能不能 new handler?為什么
必須可以。子線程 可以new 一個(gè)mainHandler,然后發(fā)送消息到UI Thread。
Android 中的動(dòng)畫有哪幾類,它們的特點(diǎn)和區(qū)別是什么
視圖動(dòng)畫,或者說補(bǔ)間動(dòng)畫。只是視覺上的一個(gè)效果,實(shí)際view屬性沒有變化,性能好,但是支持方式少。
屬性動(dòng)畫,通過變化屬性來達(dá)到動(dòng)畫的效果,性能略差,支持點(diǎn)擊等事件。android 3.0
幀動(dòng)畫,通過drawable一幀幀畫出來。
Gif動(dòng)畫,原理同上,canvas畫出來。
具體可參考:https://i.cnblogs.com/posts?categoryid=672052
如何修改 Activity 進(jìn)入和退出動(dòng)畫
overridePendingTransition
SurfaceView & View 的區(qū)別
view的更新必須在UI thread中進(jìn)行
surfaceview會(huì)單獨(dú)有一個(gè)線程做ui的更新。
surfaceview 支持open GL繪制。
開發(fā)中都使用過哪些框架、平臺(tái)
I.EventBus 事件分發(fā)機(jī)制,由handler實(shí)現(xiàn),線程間通信
II.xUtils->DbUtils,ViewUtils,HttpUtils,BitmapUtils
III.百度地圖
IV.volley
V.fastjson
VI.picciso
VII.友盟
VIII.zxing
IX.Gson
使用過那些自定義View
pull2RefreshListView
第三方登陸
QQ & 微信都有第三方登陸的sdk,要去注冊app