Be an interviewer

在問題的最右處對(duì)問題進(jìn)行等級(jí)評(píng)定,層層深入

1.Android線程之間的異步通信有哪些?(C)

handler.sendMessage AsyncTask View.post(Runnable) Activity.runOnUiThread Loaders等

  • 1-1handler深入,looper,messageQueue是怎么合作工作的(B)

在ActivityThread啟動(dòng)main方法中,會(huì)去創(chuàng)建looper對(duì)象,并且與主線程進(jìn)行綁定.一個(gè)線程只有一個(gè)looper,這個(gè)looper管理著自己的messageQueue,創(chuàng)建綁定完之后就進(jìn)入了無限循環(huán)從messageQueue中取消息,只要應(yīng)用不退出,就無限循環(huán).接著只要我們?cè)谥骶€程中新建handler對(duì)象,就會(huì)跟創(chuàng)建該handler的線程的looper綁定(在handler的構(gòu)造函數(shù)中),之后looper負(fù)責(zé)將handler send出來的message加入到queue的尾部,然后再由looper負(fù)責(zé)將message從queue的頭取出(經(jīng)過loop方法中的dispatchMessage進(jìn)行消息分發(fā)),執(zhí)行handleMessage.

1-1-1可以直接在線程中直接new一個(gè)handler出來使用么?要注意什么呢?如果不注意會(huì)報(bào)什么錯(cuò)誤呢?(A)

在子線程中創(chuàng)建handler的時(shí)候一定要注意創(chuàng)建的時(shí)候需要同時(shí)去創(chuàng)建looper,否則會(huì)由于在子線程中沒有綁定的looper對(duì)象而報(bào)錯(cuò).報(bào)錯(cuò)無能直接在子線程中建立handler的錯(cuò)誤.

1-1-2android在啟動(dòng)了之后為什么可以直接在activity中new一個(gè)handler進(jìn)行使用呢(A)

因?yàn)樵贏ctivityThread中系統(tǒng)已經(jīng)幫主線程創(chuàng)建并且綁定好了looper,這個(gè)時(shí)候只要new一個(gè)handler,在handler的構(gòu)造函數(shù)中就會(huì)自動(dòng)的將handler自身與looper進(jìn)行綁定

  • 1-2asynctask是怎么使用的呢?怎么構(gòu)建,方法怎么調(diào)用?三個(gè)參數(shù)傳入的分別是什么呢?(C)

自定義后通過new出來對(duì)象,執(zhí)行對(duì)象的excute方法實(shí)現(xiàn). 常見的方法onPreExecute和onPostExecute分別在doinbackground方法前后執(zhí)行,doinbackground負(fù)責(zé)在子線程中執(zhí)行任務(wù),然后將結(jié)果交由onPostExcute在主線程中處理,同時(shí)可以由onProgressUpdate來進(jìn)行實(shí)時(shí)的將處理狀態(tài)返回給主線程處理.定義時(shí)的三個(gè)參數(shù),依次為傳入的參數(shù)類型;第二個(gè)參數(shù)為后臺(tái)處理的進(jìn)度顯式類型,是int還是float還是其他;第三個(gè)參數(shù)是doinbackground執(zhí)行之后return給onPostExecute接受的結(jié)果類型.

1-2-1asynctask在使用的過程中哪些方法可以進(jìn)行UI操作呢?(B)

直接去AsyncTask中去看有MainThread標(biāo)注的都是可以在主線程中執(zhí)行的
onPostExecute onProgressUpdate onPreExecute onCancelled 其實(shí)都可以講的通

1-2-2asynctask的最高同時(shí)執(zhí)行線程數(shù),可以改么?怎么改?(A)

在3.0以前,支持并行處理,也就是說同時(shí)可以執(zhí)行多個(gè)任務(wù),當(dāng)時(shí)是寫死的線程池,同時(shí)可以處理的最大線程數(shù)為5個(gè),線程池大小位128,如果同時(shí)添加超過128個(gè)AsyncTask任務(wù),那么系統(tǒng)就會(huì)崩潰.3.0之后改成了串行處理,同時(shí)只能處理一個(gè)任務(wù).其實(shí)不然,其實(shí)3.0之后變得更加靈活,可以自己去定義Executor

Executor exec = new ThreadPoolExecutor(15, 200, 10,  
        TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());  
new DownloadTask().executeOnExecutor(exec);  

傳入的三個(gè)參數(shù)分別表示,可并行執(zhí)行的最大的線程數(shù),線程池大小,和超過內(nèi)核數(shù)的線程最多可以存活的時(shí)間(比如我們有10個(gè)線程,內(nèi)核數(shù)為4核,那么多下來的6個(gè)線程,最多可以存活如上所述的10秒)

1-2-3asynctask的弊端,(輪個(gè)數(shù)評(píng)級(jí),A↑)

  1. 使用cancel方法時(shí)無法直接停止子線程,由于調(diào)用了cancel方法會(huì)去調(diào)用子線程的interrupt方法,但是這個(gè)方法不會(huì)直接停止子線程而是只是更改一個(gè)標(biāo)志位,具體的停止操作需要用戶在線程中自己做監(jiān)聽.所以oncancel的真正起作用的只不過是不會(huì)去調(diào)用onPostExecute
  1. onPostExecute的時(shí)候回調(diào)出來,activity或者fragment對(duì)象已經(jīng)被銷毀的話就會(huì)出現(xiàn)找不到對(duì)象的錯(cuò)誤.這個(gè)時(shí)候要么做空判斷,要么自己定義抽象類BaseAsyncTask復(fù)寫onPostExecute,并final它
  2. 內(nèi)存泄露,在activity的匿名內(nèi)部類AsyncTask,由于AsyncTask的生命周期和activity不同步,當(dāng)activity被銷毀的時(shí)候,可能asynctask還在執(zhí)行,那么后者持有的前者對(duì)象就會(huì)難以釋放,導(dǎo)致內(nèi)存泄露.
  3. 當(dāng)asynctask在執(zhí)行的時(shí)候,activity由于屏幕旋轉(zhuǎn)或其他原因?qū)е轮亟?asyncTask由于持有的是之前的activity的引用,就會(huì)導(dǎo)致onPostExecute的代碼不起作用.
  • 1-3 主線程阻塞超過幾秒出現(xiàn)ANR,數(shù)據(jù)庫阻塞呢?廣播接受阻塞呢?(B)

主線程5秒未響應(yīng),數(shù)據(jù)庫10秒,廣播10秒未相應(yīng),會(huì)出現(xiàn)ANR

  • 1-4 View.post(runnable)可以執(zhí)行耗時(shí)的操作么?為什么?(B)

不可以執(zhí)行耗時(shí)操作,View.post出來的runnable是在UI線程中執(zhí)行的.

2.平時(shí)在使用listview的時(shí)候都會(huì)注意哪些問題?(C)

圖片的異步加載方面,性能優(yōu)化方面(ViewHolder, convertView,滑動(dòng)的時(shí)候不加載圖片等)

  • 2-1在listview中需要加載圖片的話有什么比較好的方法么?(B)

采用異步加載的方式,當(dāng)然可以使用第三方的圖片庫picasso,fresco,也可以自己實(shí)現(xiàn).

2-1-1 知道怎么去寫一個(gè)imageloader么?(A)

簡(jiǎn)易的imageLoader負(fù)責(zé)圖片的異步加載,方法可以不止一個(gè).
將圖片的url設(shè)置為view的tag,將view傳給imageloader,imageloader本身管理著一套lru緩存,將url取出后,先去緩存中查看是否有該圖片,有的話直接回調(diào)顯示,沒有的話進(jìn)行網(wǎng)絡(luò)請(qǐng)求,得到結(jié)果候進(jìn)行網(wǎng)絡(luò)顯示并做本地緩存.如果加載失敗則顯式失敗的畫面的.

2-1-2 有哪些第三方好用的圖片庫,看過源碼么,可以講一講么,區(qū)別,推薦(A+)

picasso, fresco, glide, Universal-image-loader
如果預(yù)見項(xiàng)目中會(huì)有很多圓角或漸進(jìn)式JPEG等需求,可以使用Fresco;
如果是老項(xiàng)目已經(jīng)使用了UIL或者Picasso,且依賴較多不容易修改,則可以繼續(xù)使用;
如果還在糾結(jié)如何避免65K方法數(shù),推薦使用Glide代替Fresco 因?yàn)镚lide比后者實(shí)在輕巧了太多;
如果是老項(xiàng)目需要換加載庫,推薦使用Glide而不是Fresco, 降低遷移工作量;
如果是新項(xiàng)目,不推薦使用已經(jīng)停止維護(hù)的UIL,也不推薦Picasso,推薦使用Glide;

  • 2-2 如果使用過程中出現(xiàn)了不同的item需要展示不同的布局,這個(gè)時(shí)候用什么方法解決?(B)

使用listView的viewtype去區(qū)別不同的展示

  • 2-3 listview怎么去和數(shù)據(jù)庫做綁定呢?(B)

使用cursorAdapter去實(shí)現(xiàn)和數(shù)據(jù)庫的綁定

2-3-1 如果想要listview對(duì)數(shù)據(jù)庫做實(shí)時(shí)的更新,會(huì)怎么做呢?(A)

使用cursorLoader綁定listview,用觀察者模式對(duì)數(shù)據(jù)庫進(jìn)行監(jiān)聽,一旦有變化,swapcursor,并notifyDataChanged

3. 有使用過自定義控件么,自定義控件從定義到使用,怎么個(gè)流程,可以粗略的講一下么(B-A)

  1. 首先我們需要去attr.xml文件中去定義我們控件中需要的一些自定義的屬性.
  1. 然后創(chuàng)建我們自定義的控件繼承View,主要好復(fù)寫onDraw,onLayout,和onMeasure方法,以及它的構(gòu)造函數(shù).
  2. onMeasure中根據(jù)傳入的寬高mode,來選擇是否要對(duì)控件進(jìn)行計(jì)算.如果是wrap_content的則將控件的寬高計(jì)算出來setMeasureDimension
  3. onLayout,經(jīng)過計(jì)算過后的measure寬高來獲得控件的坐標(biāo)點(diǎn),導(dǎo)入onLayout
  4. 最后在onDraw方法中,利用畫布畫筆對(duì)需要的背景或者其他內(nèi)部元素進(jìn)行繪制.
  5. 在布局文件中,添加自定義view,與自定義命名空間,來使用該自定義控件的屬性.
  • 3-1 如果我需要為這個(gè)自定義控件創(chuàng)建一些特有的屬性,比如說想要在布局文件中控制它的字體大小,字體顏色,應(yīng)該怎么去做?(A)

在attr文件中定義自定義屬性,然后在自定義控件的構(gòu)造函數(shù)中通過TypeArray取出,然后對(duì)其遍歷index,取出屬性值,做相應(yīng)處理.

  • 3-2 除了使用動(dòng)畫之外,還有什么方法可以實(shí)現(xiàn)一個(gè)動(dòng)態(tài)的view?(B)

可以使用surfaceView

3-2-1 surfaceview和一般的view有什么地方不同?(B)

一般的view都是在主線程中進(jìn)行繪制的,而surfaceView是獨(dú)立線程進(jìn)行繪制,因此可以進(jìn)行復(fù)雜的繪制,不會(huì)阻塞主線程.

3-2-2 你覺得什么情景中會(huì)使用到surfaceview,或者你知道什么地方會(huì)用到surfaceview(A)

相機(jī)模塊中會(huì)使用到,或者是復(fù)雜的動(dòng)畫顯示,或者是一些游戲界面也會(huì)食用到,只要是畫面在不斷的變化的就可以使用surfaceView去實(shí)現(xiàn).

3-2-3 在使用surfaceview的時(shí)候需要注意一些什么?什么時(shí)候畫,什么時(shí)候不畫?怎么去做(A)

注意啟動(dòng)和關(guān)閉繪制.由于它的特殊性,我們可以在onResume中啟動(dòng)繪制,在onPause中停止繪制.
由于自定義的surfaceView需要去實(shí)現(xiàn)runnable,在類內(nèi)部實(shí)現(xiàn)其run方法,我們可以設(shè)置一個(gè)標(biāo)志位,在run方法中進(jìn)行循環(huán)判斷,一旦標(biāo)志位為false就停止繪制,然后可以在view的onPause和onResume中修改標(biāo)志位.

4.有沒有NDK編程經(jīng)驗(yàn),或者說對(duì)NDK有了解么?(C)

結(jié)合C或C++,進(jìn)行android編程,一般使用比較多的是方法封裝,編譯成so庫文件,供android項(xiàng)目使用.

  • 4-1 講一下NDK的一個(gè)大體流程,或者說現(xiàn)在給你一個(gè)工具類,如何去調(diào)用C代碼的一些方法?(B)
  1. 首先需要使用NDK生成相應(yīng)的頭文件,或者是自己寫也行.然后新建.c文件,引用該頭文件,然后注意定義的與java交接的方法名需要與調(diào)用該方法的類的包名相同,要遵循相應(yīng)的規(guī)則.
  1. 然后在c文件中,實(shí)現(xiàn)該方法.之后在gradle中對(duì)其進(jìn)行配置.執(zhí)行NDK編譯,在build目錄下得到相應(yīng)文件夾的so文件,將so文件放入jniLib中.
  2. 在工具類中靜態(tài)加載so庫,然后調(diào)用相應(yīng)方法即可生效.
  • 4-1-1 eclipse上的NDK編程和studio上的有什么不同?(A)

eclipse上需要通過Android.mk和application.mk去對(duì)該NDK項(xiàng)目進(jìn)行配置,而在studio上直接在gradle中進(jìn)行配置即可.

5. 對(duì)當(dāng)今比較流行的框架有了解么?可以舉出你知道的一些框架么?(B)

網(wǎng)絡(luò)框架 retrofit,Okhttp,volly等 緩存DIskLruCache等 數(shù)據(jù)庫OrmLite,GreenDao等, 依賴注入Dagger2 butterKnife等 事件總線 eventBus等 RX響應(yīng)式編程 內(nèi)存泄露LeakCanary等等有很多

  • 5-1 看過框架的源碼么?講一下框架大概原理,是怎么工作的?(A↑)

看具體回答評(píng)級(jí)

  • 5-2 知道RN,聽說過熱修復(fù)么?動(dòng)態(tài)加載,插件化知道多少?(A↑)

reactive-native利用js, html, css重新定義一套規(guī)則, 編寫原生的ios,android移動(dòng)應(yīng)用.
hotfix,利用動(dòng)態(tài)加載技術(shù),在用戶手機(jī)崩潰時(shí),調(diào)用遠(yuǎn)程服務(wù)端的可執(zhí)行文件,待遠(yuǎn)程將問題解決了之后,現(xiàn)場(chǎng)修復(fù),替換掉有問題的坑,再讓手機(jī)執(zhí)行修復(fù)后的本地文件,避免了頻繁的版本更新.比較熱門方案的有AndFix, DexPosed, ClassLoader.熱門的實(shí)現(xiàn)有Nuwa,HotFix,DroidFix.
而動(dòng)態(tài)加載和插件化開發(fā)可以方便大規(guī)模團(tuán)隊(duì)協(xié)同開發(fā), 技術(shù)也應(yīng)用于熱補(bǔ)丁修復(fù),將項(xiàng)目開發(fā)模塊化分散.
內(nèi)容比較多,上面也只是個(gè)大概,具體看怎么去回答,根據(jù)回答的詳細(xì)情況,了解情況來進(jìn)行評(píng)級(jí).

6.對(duì)整個(gè)手機(jī)的布局有了解么?畫一下整個(gè)的手機(jī)布局框架(B)

觀察是否有phoneWindow和decorView的概念

  • 6-1 Activity,View,Window的關(guān)系是什么?(B)

我們?cè)赼ctivity的attach方法中,會(huì)去生成window,就是整個(gè)手機(jī)的最根的布局,而這個(gè)window的實(shí)現(xiàn)類是phoneWindow,在phoneWindow中有一個(gè)最頂層的視圖DecorView, 由phoneWIndow將布局文件進(jìn)行解析,然后將相應(yīng)的view加載到DecorVIew中.

  • 6-1-1 setcontentView到底是怎么樣把布局文件讓手機(jī)屏幕展示出來的(A)

phoneWindow得setContentView方法來將activity的setContentView的布局文件加載到視圖中去,這就是這三者的關(guān)系。實(shí)際上直接看setContentView的源碼實(shí)現(xiàn)就知道它調(diào)用了getWindow().setContentView()再點(diǎn)開發(fā)現(xiàn)是空實(shí)現(xiàn),因?yàn)檎嬲膶?shí)現(xiàn)就在phoneWindow中。

7. 四個(gè)lunchmode(C)

standard,singleTop,singleTask,singleInstance

  • 7-1 分別介紹一下使用場(chǎng)景(B)

singleTop 直接吊起activity棧的最頂部activity。 點(diǎn)擊通知推送需要進(jìn)入到一個(gè)界面,那么如果收到多個(gè)推送的話,停留在這個(gè)界面去點(diǎn)擊這個(gè)推送就不用再去重新生成這個(gè)界面activity。
singleTask 啟動(dòng)activity棧中的該activity,并把其上的所有activity清空。 一般用在程序的入口,比如從好幾個(gè)應(yīng)用啟動(dòng)了瀏覽器,只會(huì)啟動(dòng)瀏覽器的主界面一次,瀏覽器主界面之后的activity都會(huì)清空掉。
singleInstance 特地為個(gè)別activity單獨(dú)建立一個(gè)activity的棧,多次重復(fù)利用。 某個(gè)應(yīng)用中用到了google地圖,當(dāng)退出該應(yīng)用再次進(jìn)入google地圖的時(shí)候,還是停留在剛才的畫面。** **

  • 7-2 使用singleTask時(shí)候會(huì)遇到什么問題么?(A↑)比如用startActivityForResult去調(diào)用singleTask的activity會(huì)出現(xiàn)什么現(xiàn)象呢?(A)

啟動(dòng)singleTask和singleInstance這兩類模式的activity的時(shí)候,需要注意不要去用startActivityForResult方法調(diào)用,回立馬收到cancel的回調(diào).

  • 7-2-1 那么singleInstance呢?(A)

  • 7-2-2 如果A真的想要用startActivityForResult去啟動(dòng)singleTask的B的話怎么辦?(A)

直接在B中再將需要回傳的數(shù)據(jù)通過startActivty(A)的方式去啟動(dòng)A.

8. 大體講一下觸摸事件分發(fā)吧(B↑)

隧道式的分發(fā),冒泡式的反饋,一路直接到可以處理觸摸事件的view,然后一路向上按照分發(fā)下來的路徑反向反饋。
最外層的布局調(diào)它的dispatchTouchEvent方法,在方法中會(huì)去看能否攔截,如果可以且需要攔截那就攔截不往下傳遞,否則的話遍歷找到符合條件的子view去調(diào)用它的dispatchTouchEvent,知道最終消費(fèi)處理這個(gè)點(diǎn)擊事件的子view的dispatch方法返回true,然后就不往下傳遞,并往上走出這個(gè)遞歸,這就是viewGroup和view之間的事件分發(fā)機(jī)制,結(jié)合view自己的分發(fā)就可以完美解答這個(gè)問題。

  • 8-1 intercept返回true,false分別表示什么意思?dispatchTouchEvent呢?onTouchEvent呢?(B)

intercept返回true表示攔截了,onTouch返回true表示被我監(jiān)聽器消耗了,onTouchEvent表示被我view自己吃了,然后dispatchTouchEvent表示被我這個(gè)view處理消耗了??偟膩碚f就是返回true代表不往下繼續(xù)傳遞,開始往上傳遞了.

  • 8-2 onclick, ontouch,ontouchevent的執(zhí)行的順序是什么?(B)你是怎么知道的(A)

一段源碼告訴你,在View的dispatchTouchEvent中,onclick是寫在onTouchEvent中的。



所以正確的順序應(yīng)該是onTouch ----> onTouchEvent --------> onClick

9. android的跨進(jìn)程通信知道那些?(B)

  (1) activity的startActivity方式,activity可以直接通過filter去啟動(dòng)其他應(yīng)用中定義了intent-filter的activity,然后進(jìn)行跨進(jìn)程通信
  (2) content provider的跨進(jìn)程共享數(shù)據(jù)
  (3) 廣播的被動(dòng)跨進(jìn)程通信
  (4) AIDL的binder機(jī)制。  
  • 9-1 單單從耦合度分析,廣播機(jī)制和binder機(jī)制有什么不同呢?(B)

廣播的發(fā)送者和接收者互相都是不知道對(duì)方的,而binder則不同,相比前者耦合度更低,可拓展性更強(qiáng).

9-1-1 廣播的靜態(tài)注冊(cè)和動(dòng)態(tài)注冊(cè)分別是怎么實(shí)現(xiàn)的呢?有什么不同呢?(B)

靜態(tài)注冊(cè)是在androidManifest文件中進(jìn)行receiver注冊(cè),設(shè)置相應(yīng)的intentfilter的action;動(dòng)態(tài)注冊(cè)直接在代碼中進(jìn)行receiver注冊(cè).不同的地方在于動(dòng)態(tài)注冊(cè)的廣播可以進(jìn)行unRegister,且退出應(yīng)用了之后就不會(huì)再接收到廣播,但是靜態(tài)注冊(cè)的廣播即使退出了應(yīng)用還是會(huì)收到廣播.

10. 移動(dòng)端的網(wǎng)絡(luò)優(yōu)化,想的到哪些?(B↑)

連接復(fù)用:默認(rèn)情況下,httpurlconnection都是開通了keep-alive的功能的
合并請(qǐng)求:對(duì)于界面中出現(xiàn)頻繁請(qǐng)求的情況,可以將請(qǐng)求進(jìn)行合并,一次性請(qǐng)求。
請(qǐng)求壓縮: post請(qǐng)求,請(qǐng)求的body或者是header都可以進(jìn)行g(shù)zip壓縮; 對(duì)于返回?cái)?shù)據(jù)的格式相差不是很大的,也可以對(duì)key部分進(jìn)行壓縮。
根據(jù)用戶的網(wǎng)絡(luò)質(zhì)量,判斷下載什么質(zhì)量的圖片。本地還可以做靜態(tài)緩存。
直接訪問IP,而非域名: 使用動(dòng)態(tài)的IP列表,直接訪問IP,一旦IP不能訪問了,再用域名進(jìn)行訪問。
增量更新:對(duì)新增的數(shù)據(jù)進(jìn)行更新,bsdiff和bspatch
預(yù)連接和預(yù)取數(shù)據(jù):
對(duì)請(qǐng)求分優(yōu)先級(jí)

11. service知道多少,一個(gè)service從定義到使用大體講一下?(B)

Service是由framework層的ActivityServiceManager管理的生命周期長(zhǎng)、運(yùn)行于后臺(tái)的服務(wù)性組件。Service本身是運(yùn)行在當(dāng)前應(yīng)用進(jìn)程的主線程中,但是可以在Service中開辟子線程以實(shí)現(xiàn)音樂播放、數(shù)據(jù)庫交互、文件操作等耗時(shí)操作(因?yàn)榻^大多數(shù)情況下Service沒有前臺(tái)界面)。需要在manifest文件中聲明
service的啟動(dòng)有startService和bindService兩種方式,前者當(dāng)應(yīng)用退出時(shí),依然可以運(yùn)行,除非調(diào)用了stopself或者是系統(tǒng)調(diào)用了stopService,而后者則是通過unbindService解綁.
oncreate方法只會(huì)執(zhí)行一次,但是每次調(diào)用都會(huì)執(zhí)行onStartCommand(startService)/onBindSerivce(bindService0,當(dāng)調(diào)用了stopSelf或者是stopservice之后如果又綁定就執(zhí)行onUnBind,否則就直接執(zhí)行onDestory方法.
onstartCommand根據(jù)具體的返回值來判斷service被kill了之后如何重啟service.
那么綜上,

  1. 自定義的service繼承service,我們可以通過具體的需求選擇是復(fù)寫它的onStartCommand方法還是onBind方法去實(shí)現(xiàn).
  2. 去清單文件注冊(cè)service
  3. 通過startService的方式或者是bindService的方式來實(shí)現(xiàn).startService直接啟動(dòng)service,bindService則需要傳入ServiceConnection接口,我們可以在接口方法onServiceConnected中去做邏輯處理,或者自定義處理或者將IBinder取出做處理
  • 11-1 service和應(yīng)用是在一個(gè)進(jìn)程中么?本身是一個(gè)線程么?(B)

本身既不時(shí)線程也不是進(jìn)程,service是在主線程中進(jìn)行的.

11-1-1 intentService和service有什么不同呢?(A)

intentService不用去起新線程就可以執(zhí)行耗時(shí)的操作,內(nèi)部是利用handler來處理源源不斷的intent請(qǐng)求,將intent加入隊(duì)列,然后依次進(jìn)行處理.所以在intentService中我們只需要去實(shí)現(xiàn)onHandleIntent方法就可以了,而service是在主線程中進(jìn)行的,需要去另起線程才可以處理耗時(shí)的操作.
intentService需要定義一個(gè)構(gòu)造函數(shù),在構(gòu)造函數(shù)中調(diào)用super方法,傳入該服務(wù)的名字,來給intentService命名,因?yàn)閕ntentService不需要在manifest文件中注冊(cè).

11-1-2 intenService內(nèi)部源碼看過么?它是如何做到不用新起線程就可以去執(zhí)行耗時(shí)的操作的?(A↑)

實(shí)際上就是looper的原理。我們進(jìn)它的源碼看一看:


新起一個(gè)線程,獲得它的looper,創(chuàng)建相應(yīng)的handler
這樣他就通過handler去不斷的循環(huán)新扔進(jìn)來的intent,然后進(jìn)行處理。所以在intentService中,我們可以直接在onHandleIntent中處理耗時(shí)任務(wù)。

12. 碰到過哪些異常,講一講。(B↑)

(1) Can not perform this action after onSaveInstanceState
在Activity保存了狀態(tài)之后,再對(duì)fragmentManger進(jìn)行commit事務(wù)的操作就會(huì)造成這個(gè)錯(cuò)誤,一般最省力的辦法就是把commit改成commitAllowStateLoss
(2) NetWork on main thread
在主線程中進(jìn)行網(wǎng)絡(luò)請(qǐng)求
(3) ClassCastException
類型強(qiáng)轉(zhuǎn)錯(cuò)誤
(4) IndexOutOfBound
數(shù)組越界
(5) outOfMemory

13. 不同的屏幕分辨率,如何去適配呢?(C)

最常用的方法是用不同的分辨率文件夾,保存不同分辨率的圖片到相應(yīng)的文件夾下,對(duì)于單色圖標(biāo)來說,最好的方法是使用矢量圖來解決,既可以適配不同分辨率,又可以幫apk瘦身。
在布局方面,我們盡可能的去使用relativelayout,強(qiáng)調(diào)的組件和組件之間的位置關(guān)系,避免了直接將大小寫死,可以很好的適配不同的分辨率,最新的android.support.constraint.ConstraintLayout更是將其發(fā)揮到極致?;蛘呶覀円部梢詾椴煌钠聊蛔霾煌牟季?,放在相應(yīng)layout文件夾下。

  • 13-1 知道那些layout,和drawable文件夾?(C)

各尺寸

  • 13-1-1 hdpi和mdpi哪一個(gè)大一點(diǎn)(C)

hdpi..

14. 內(nèi)存泄露的原因知道哪些?(C)

(1)集合類
只知道添加,而沒有做好具體的刪除工作的話,那么如果遇到全局的集合變量,就會(huì)導(dǎo)致這個(gè)集合所占用的內(nèi)存只增不減
(2)單例模式
一般見得最多的就是寫的一些util類,為了需要展示或者是做一些需要context的有關(guān)操作,就需要傳入context,而為了讓Util可以直接進(jìn)行方法調(diào)用,就會(huì)將一些方法寫成static,然后本類的context對(duì)象不得不定義為static,就不得不去靜態(tài)持有外部的對(duì)象,這樣以來,當(dāng)外部對(duì)象已經(jīng)不可到達(dá)了之后(javaGC),由于被這個(gè)util持有,依然無法回收,就泄露了。
(3)Android特殊的組件需要手動(dòng)的去關(guān)閉
比如BroadCastReceiver,ContentReceiver,F(xiàn)ileObserver,Callback什么的都需要在onDestory方法或者在activity的生命周期結(jié)束的時(shí)候回收,否則activity會(huì)被系統(tǒng)強(qiáng)引用,無法回收。
(4)handler
只要handler中的message沒有被處理完,那么這個(gè)message就會(huì)和他的hander被MessageQueue一直持有,需要在相應(yīng)的位置對(duì)handler進(jìn)行removeMessageCallback等操作
(5)線程造成的內(nèi)存泄露
線程的生命周期和activity不一樣,就會(huì)導(dǎo)致activity中新起的線程,持有activity的一個(gè)引用,結(jié)果run方法還沒有結(jié)束的話,activity就不會(huì)釋放,如果此時(shí)activity早就已經(jīng)用不到了,久造成了內(nèi)存泄露。
(6)不良的代碼習(xí)慣
比如bitmap沒有及時(shí)的recycle,各種io流沒有及時(shí)的close,adapter中沒有使用convertView

  • 14-1 講一講你所知道的java的GC算法吧 (B↑)

引用計(jì)數(shù):一個(gè)對(duì)象被引用計(jì)數(shù)器加一,取消引用計(jì)數(shù)器減一,引用計(jì)數(shù)器為0才能被回收。優(yōu)點(diǎn):簡(jiǎn)單。缺點(diǎn):不能解決循環(huán)引用的問題,比如A引用B,B引用A,但是這兩個(gè)對(duì)象沒有被其他任何對(duì)象引用,屬于垃圾對(duì)象,卻不能回收;每次引用都會(huì)附件一個(gè)加減法,影響性能。
標(biāo)記清除法:分為兩個(gè)階段:標(biāo)記階段和清除階段。標(biāo)記階段通過根節(jié)點(diǎn)標(biāo)記所有可達(dá)對(duì)象,清除階段清除所有不可達(dá)對(duì)象。缺點(diǎn):因?yàn)榍宄豢蛇_(dá)對(duì)象之后剩余的內(nèi)存不連續(xù),會(huì)產(chǎn)生大量?jī)?nèi)存碎片,不利于大對(duì)象的分配。
復(fù)制算法:將內(nèi)存空間分成相同的兩塊,每次只是用其中的一塊,垃圾回收時(shí),將正在使用的內(nèi)存中的存活對(duì)象復(fù)制到另外一塊空間,然后清除正在使用的內(nèi)存空間中的所有對(duì)象,這種回收算法適用于新生代垃圾回收。優(yōu)點(diǎn):垃圾回收對(duì)象比較多時(shí)需要復(fù)制的對(duì)象恨少,性能較好;不會(huì)存在內(nèi)存碎片。缺點(diǎn):將系統(tǒng)內(nèi)存折半。
標(biāo)記壓縮算法:是一種老年代回收算法,在標(biāo)記清除的基礎(chǔ)上做了一些優(yōu)化,首先從根節(jié)點(diǎn)開始標(biāo)記所有不可達(dá)的對(duì)象,然后將所有可達(dá)的對(duì)象移動(dòng)到內(nèi)存的一端,最后清除所有不可達(dá)的對(duì)象。優(yōu)點(diǎn):不用將內(nèi)存分為兩塊;不會(huì)產(chǎn)生內(nèi)存碎片。
分代算法:新生代使用復(fù)制算法,老生帶使用標(biāo)記清除算法或者標(biāo)記壓縮算法。幾乎所有的垃圾回收期都區(qū)分新生代和老生帶。
分區(qū)算法:將整個(gè)堆空間分成很多個(gè)連續(xù)的不同的小空間,每個(gè)小空間獨(dú)立使用,獨(dú)立回收。為了更好的控制gc停頓時(shí)間,可以根據(jù)目標(biāo)停頓時(shí)間合理地回收若干個(gè)小區(qū)間,而不是整個(gè)堆空間,從而減少gc停頓時(shí)間。

  • 14-2 你所知道的哪些東西需要及時(shí)的去關(guān)閉或者是釋放的?(B)

比如BroadCastReceiver,ContentReceiver,F(xiàn)ileObserver,Callback什么的都需要在onDestory方法或者在activity的生命周期結(jié)束的時(shí)候回收,否則activity會(huì)被系統(tǒng)強(qiáng)引用,無法回收。
比如bitmap沒有及時(shí)的recycle,各種io流沒有及時(shí)的close,adapter中沒有使用convertView

15.scrollView怎么去判斷有沒有滑到了底部?(A)

首先我們判斷肯定是要放在touch監(jiān)聽當(dāng)中,比如scrollview的onTouchListener或者是他自己的onScrollChange中。
在ontouch中,當(dāng)檢測(cè)到up動(dòng)作的時(shí)候,判斷getScrollY + getHeight = view.getChildAt(0).getMeasureHeight()的時(shí)候就是到了底部
或者在onScrollChange方法中,通過View view = (View)getchildAt(getChildCount() - 1)獲得最下面的一個(gè)view(其實(shí)就是scrollView包裹的唯一子view),然后獲得它的高度,view.getBottom(),然后當(dāng)這個(gè)高度等于scrollY+ getHeight的時(shí)候就是滑到了底部

  • 15-1 getScrollY()表示什么意思?

可以理解位控件上方滑出屏幕的距離,如果為負(fù),就表示已經(jīng)滑到了控件的頂端

16. assets和raw有什么不同和相同?(C)

兩個(gè)文件夾的文件都不會(huì)跟著壓制apk被編譯壓縮,都是原封不動(dòng)的保存。raw文件下不可以再有目錄,而assets文件下可以再有目錄
raw文件夾下面的文件會(huì)映射到R文件中,調(diào)用的時(shí)候直接去使用R.raw.xxxx就可以訪問,getResources().openRawResource(R.raw.rawtext)
而assets文件下的文件訪問的時(shí)候需要用到AssetManager,AssetManager assets = getAssets(); assets.open(123.txt);

  • 16-1 什么時(shí)候用assets,什么時(shí)候去用raw

有些文件不得不放在raw中,因?yàn)橹苯涌梢酝ㄟ^R文件去訪問,可以直接在xml文件中去訪問他,而assets中由于沒有產(chǎn)生R文件的映射,訪問的速度應(yīng)該是沒有Raw文件來的快的。

17. 數(shù)據(jù)持久化的四中方式?(B)

preference,SQlite,文件I/O,ContentProvider

18. 顯式和隱式的intent調(diào)用分別怎么調(diào)用?(C)

顯式:intent直接定義的時(shí)候傳入指定的class,或者是component,或者是setClass/setClassName
隱式:不明確指定具體的class,而是采用setAction的方式,來啟動(dòng)注冊(cè)了添加了這個(gè)action的filter的activity。如果找到一個(gè)就打開一個(gè),如果找到多個(gè),系統(tǒng)會(huì)讓你進(jìn)行選擇,,如果一個(gè)都沒有找到,就跳出來activitynotfoundexception

19. 自定義viewgroup,實(shí)現(xiàn)過么?(C)

繼承自ViewGroup,主要的就是實(shí)現(xiàn)onMeasure方法和onLayout方法,因?yàn)閛nDraw方法只需要調(diào)用super.onDraw方法即可。
在onMeasure,根據(jù)獲得父框架給予的寬高大小和寬高模式,來計(jì)算子view排布之后的布局的寬高。如果在xml文件中直接定義了dp的具體數(shù)值,或者是直接是match_parent,則直接調(diào)用setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY)?sizeWidth: width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight: height); 根據(jù)尺寸模式來判斷是要使用自己計(jì)算出來的寬高還是父框架給予的寬高
在onLayout中,就對(duì)子view進(jìn)行排布。定義left = 0,和top = 0,然后根據(jù)分布的規(guī)則,遍歷自view,計(jì)算出他們的left,top,right,bottom的值,然后調(diào)用自view的layout方法,去排列它們

  • 19-1 具體需要實(shí)現(xiàn)哪些方法呢?(B)

onMeasure, onLayout,依據(jù)情況還可以實(shí)現(xiàn)onDraw等方法

19-1-1 知道流布局么,讓你實(shí)現(xiàn)怎么實(shí)現(xiàn),大體講一講?(A)

通過onMeasure對(duì)內(nèi)部組件進(jìn)行遍歷計(jì)算寬度和高度,如果內(nèi)部組件的寬度和(包括margin)比父類給予的寬度大了就開第二行進(jìn)行計(jì)算,并疊加高度,.依次來進(jìn)行計(jì)算控件的寬高,然后調(diào)用setMeasureDimension.
通過onLayout來計(jì)算坐標(biāo)點(diǎn),計(jì)算方式跟onMeasure方式相同,只是寬高存儲(chǔ)改為坐標(biāo)存儲(chǔ).

20. 題外問題

  • 20-1 為什么android的包名用com.xxxx.xxxx方式?(C)

java項(xiàng)目遺留下來的不成文的規(guī)定,習(xí)慣問題,com代表公司,org代表個(gè)人,也完全可以用自己喜歡的方式,主要就是為了防止出現(xiàn)包名重復(fù)出現(xiàn)問題.

21.自定義問題

  • 21-1 五個(gè)控件,左右頂格,距離相等,horizental

22.什么叫事件驅(qū)動(dòng)

通過行為動(dòng)作比如一個(gè)點(diǎn)擊,一個(gè)觸摸等等,程序就會(huì)給出相應(yīng)的反饋,就是事件驅(qū)動(dòng)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,745評(píng)論 25 709
  • 或許有一天是這樣的結(jié)果 放棄一生的文字和符號(hào) 忠于山川和河流 四月四的雨水沒有了溫柔 扎進(jìn)我沉睡的心口 我沒有春天...
    城鎮(zhèn)中的酒館閱讀 217評(píng)論 2 2
  • 一人獨(dú)等熱粥涼,兩碗下肚不放糖。 嘗盡平常常常靜,望盡過往往往傷!
    年素衣閱讀 207評(píng)論 0 3

友情鏈接更多精彩內(nèi)容