如何才能經過一線互聯網公司面試?請掌握這些!

1.如何導入外部數據庫?

把原數據庫包括在項目源碼的 res/rawjava

android系統下數據庫應該存放在 /data/data/com.android

.

(package name)/ 目錄下,因此咱們須要作的是把已有的數據庫傳入那個目錄下.操做方法是用FileInputStream讀取原數據庫,再用FileOutputStream把讀取到的東西寫入到那個目錄.數據庫


2.本地廣播和全局廣播有什麼差異?

因廣播數據在本應用範圍內傳播,不用擔憂隱私數據泄露的問題。
不用擔憂別的應用僞造廣播,形成安全隱患。
相比在系統內發送全局廣播,它更高效。
canvas


3.intentService做用是什麼,AIDL解決了什麼問題-小米

生成一個默認的且與主線程互相獨立的工做者線程來執行全部傳送至onStartCommand() 方法的Intetnt。瀏覽器

生成一個工做隊列來傳送Intent對象給你的onHandleIntent()方法,同一時刻只傳送一個Intent對象,這樣一來,你就沒必要擔憂多線程的問題。在全部的請求(Intent)都被執行完之後會自動中止服務,因此,你不須要本身去調用stopSelf()方法來中止。緩存

該服務提供了一個onBind()方法的默認實現,它返回null安全

提供了一個onStartCommand()方法的默認實現,它將Intent先傳送至工做隊列,而後從工做隊列中每次取出一個傳送至onHandleIntent()方法,在該方法中對Intent對相應的處理。bash

AIDL (Android Interface Definition Language) 是一種IDL 語言,用於生成能夠在Android設備上兩個進程之間進行進程間通訊(interprocess communication, IPC)的代碼。若是在一個進程中(例如Activity)要調用另外一個進程中(例如Service)對象的操做,就可使用AIDL生成可序列化的參數。
AIDL IPC機制是面向接口的,像COM或Corba同樣,可是更加輕量級。它是使用代理類在客戶端和實現端傳遞數據。微信

4.Ubuntu編譯安卓系統-百度

  1. 進入源碼根目錄
  2. . build/envsetup.sh
  3. lunch
  4. full(編譯所有)
  5. userdebug(選擇編譯版本)
  6. make -j8(開啓8個線程編譯)

5.LaunchMode應用場景-百度-小米-樂視

standard,建立一個新的Activity。數據結構

singleTop,棧頂不是該類型的Activity,建立一個新的Activity。不然,onNewIntent。

singleTask,回退棧中沒有該類型的Activity,建立Activity,不然,onNewIntent+ClearTop。

注意:

  1. 設置了"singleTask"啓動模式的Activity,它在啓動的時候,會先在系統中查找屬性值affinity等於它的屬性值taskAffinity的Task存在; 若是存在這樣的Task,它就會在這個Task中啓動,不然就會在新的任務棧中啓動。所以, 若是咱們想要設置了"singleTask"啓動模式的Activity在新的任務中啓動,就要爲它設置一個獨立的taskAffinity屬性值。
  2. 若是設置了"singleTask"啓動模式的Activity不是在新的任務中啓動時,它會在已有的任務中查看是否已經存在相應的Activity實例, 若是存在,就會把位於這個Activity實例上面的Activity所有結束掉,即最終這個Activity 實例會位於任務的Stack頂端中。
  3. 在一個任務棧中只有一個」singleTask」啓動模式的Activity存在。他的上面能夠有其餘的Activity。這點與singleInstance是有區別的。

singleInstance,回退棧中,只有這一個Activity,沒有其餘Activity。

singleTop適合接收通知啓動的內容顯示頁面。

例如,某個新聞客戶端的新聞內容頁面,若是收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人的。

singleTask適合做爲程序入口點。

例如瀏覽器的主界面。無論從多少個應用啓動瀏覽器,只會啓動主界面一次,其他狀況都會走onNewIntent,而且會清空主界面上面的其餘頁面。

singleInstance應用場景:

鬧鈴的響鈴界面。 你之前設置了一個鬧鈴:上午6點。在上午5點58分,你啓動了鬧鈴設置界面,並按 Home 鍵回桌面;在上午5點59分時,你在微信和朋友聊天;在6點時,鬧鈴響了,而且彈出了一個對話框形式的 Activity(名爲 AlarmAlertActivity) 提示你到6點了(這個 Activity 就是以 SingleInstance 加載模式打開的),你按返回鍵,回到的是微信的聊天界面,這是由於 AlarmAlertActivity 所在的 Task 的棧只有他一個元素, 所以退出以後這個 Task 的棧空了。若是是以 SingleTask 打開 AlarmAlertActivity,那麼當鬧鈴響了的時候,按返回鍵應該進入鬧鈴設置界面。

6.多線程-360

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable),View.postDelay(Runnable,long)
  • Handler
  • AsyncTask

7.Handler,Thread和HandlerThread的差異-小米

從Android中Thread(java.lang.Thread -> java.lang.Object)描述能夠看出,Android的Thread沒有對Java的Thread作任何封裝,可是Android提供了一個繼承自Thread的類HandlerThread(android.os.HandlerThread -> java.lang.Thread),這個類對Java的Thread作了不少便利Android系統的封裝。

android.os.Handler能夠經過Looper對象實例化,並運行於另外的線程中,Android提供了讓Handler運行於其它線程的線程實現,也是就HandlerThread。HandlerThread對象start後能夠得到其Looper對象,而且使用這個Looper對象實例Handler。

8.什麼狀況致使內存泄漏-美團

8.1.資源對象沒關閉形成的內存泄漏

描述:
資源性對象好比(Cursor,File文件等)每每都用了一些緩衝,咱們在不使用的時候,應該及時關閉它們,以便它們的緩衝及時回收內存。它們的緩衝不只存在於 java虛擬機內,還存在於java虛擬機外。若是咱們僅僅是把它的引用設置爲null,而不關閉它們,每每會形成內存泄漏。由於有些資源性對象,好比 SQLiteCursor(在析構函數finalize(),若是咱們沒有關閉它,它本身會調close()關閉),若是咱們沒有關閉它,系統在回收它時也會關閉它,可是這樣的效率過低了。所以對於資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,而後才置爲null.在咱們的程序退出時必定要確保咱們的資源性對象已經關閉。
程序中常常會進行查詢數據庫的操做,可是常常會有使用完畢Cursor後沒有關閉的狀況。若是咱們的查詢結果集比較小,對內存的消耗不容易被發現,只有在常時間大量操做的狀況下才會復現內存問題,這樣就會給之後的測試和問題排查帶來困難和風險。

8.2.構造Adapter時,沒有使用緩存的convertView

描述:
以構造ListView的BaseAdapter爲例,在BaseAdapter中提供了方法:
public View getView(int position, ViewconvertView, ViewGroup parent)
來向ListView提供每個item所須要的view對象。初始時ListView會從BaseAdapter中根據當前的屏幕布局實例化必定數量的 view對象,同時ListView會將這些view對象緩存起來。當向上滾動ListView時,原先位於最上面的list item的view對象會被回收,而後被用來構造新出現的最下面的list item。這個構造過程就是由getView()方法完成的,getView()的第二個形參View convertView就是被緩存起來的list item的view對象(初始化時緩存中沒有view對象則convertView是null)。由此能夠看出,若是咱們不去使用 convertView,而是每次都在getView()中從新實例化一個View對象的話,即浪費資源也浪費時間,也會使得內存佔用愈來愈大。 ListView回收list item的view對象的過程能夠查看:
android.widget.AbsListView.java --> voidaddScrapView(View scrap) 方法。
示例代碼:

public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = new Xxx(...); 
... ... 
return view; 
} 複製代碼

修正示例代碼:

public View getView(int position, ViewconvertView, ViewGroup parent) {
View view = null; 
if (convertView != null) { 
view = convertView; 
populate(view, getItem(position)); 
... 
} else { 
view = new Xxx(...); 
... 
} 
return view; 
} 複製代碼

8.3.Bitmap對象不在使用時調用recycle()釋放內存

描述:
有時咱們會手工的操做Bitmap對象,若是一個Bitmap對象比較佔內存,當它不在被使用的時候,能夠調用Bitmap.recycle()方法回收此對象的像素所佔用的內存,但這不是必須的,視狀況而定。能夠看一下代碼中的註釋:

/** 
•Free up the memory associated with thisbitmap's pixels, and mark the •bitmap as "dead", meaning itwill throw an exception if getPixels() or •setPixels() is called, and will drawnothing. This operation cannot be •reversed, so it should only be called ifyou are sure there are no •further uses for the bitmap. This is anadvanced call, and normally need •not be called, since the normal GCprocess will free up this memory when •there are no more references to thisbitmap. */ 複製代碼

8.4.試着使用關於application的context來替代和activity相關的context

這是一個很隱晦的內存泄漏的狀況。有一種簡單的方法來避免context相關的內存泄漏。最顯著地一個是避免context逃出他本身的範圍以外。使用Application context。這個context的生存週期和你的應用的生存週期同樣長,而不是取決於activity的生存週期。若是你想保持一個長期生存的對象,而且這個對象須要一個context,記得使用application對象。你能夠經過調用 Context.getApplicationContext() or Activity.getApplication()來得到

8.5.註冊沒取消形成的內存泄漏

一些Android程序可能引用咱們的Anroid程序的對象(好比註冊機制)。即便咱們的Android程序已經結束了,可是別的引用程序仍然還有對咱們的Android程序的某個對象的引用,泄漏的內存依然不能被垃圾回收。調用registerReceiver後未調用unregisterReceiver。

好比:假設咱們但願在鎖屏界面(LockScreen)中,監聽系統中的電話服務以獲取一些信息(如信號強度等),則能夠在LockScreen中定義一個 PhoneStateListener的對象,同時將它註冊到TelephonyManager服務中。對於LockScreen對象,當須要顯示鎖屏界面的時候就會建立一個LockScreen對象,而當鎖屏界面消失的時候LockScreen對象就會被釋放掉。

可是若是在釋放 LockScreen對象的時候忘記取消咱們以前註冊的PhoneStateListener對象,則會致使LockScreen沒法被垃圾回收。若是不斷的使鎖屏界面顯示和消失,則最終會因爲大量的LockScreen對象沒有辦法被回收而引發OutOfMemory,使得system_process 進程掛掉。

雖然有些系統程序,它自己好像是能夠自動取消註冊的(固然不及時),可是咱們仍是應該在咱們的程序中明確的取消註冊,程序結束時應該把全部的註冊都取消掉。

8.6.集合中對象沒清理形成的內存泄漏

咱們一般把一些對象的引用加入到了集合中,當咱們不須要該對象時,並無把它的引用從集合中清理掉,這樣這個集合就會愈來愈大。若是這個集合是static的話,那狀況就更嚴重了。

9.什麼狀況致使oom-樂視-美團

1)使用更加輕量的數據結構
2)Android裏面使用Enum
3)Bitmap對象的內存佔用
4)更大的圖片
5)onDraw方法裏面執行對象的建立
6)StringBuilder

10.Service與Activity之間通訊的幾種方式

  • 經過Binder對象
  • 經過broadcast(廣播)的形式

11.如何保證service在後臺不被Kill

一.onStartCommand方法,返回START_STICKY

  1. START_STICKY
    在運行onStartCommand後service進程被kill後,那將保留在開始狀態,可是不保留那些傳入的intent。不久後service就會再次嘗試從新建立,由於保留在開始狀態,在建立 service後將保證調用onstartCommand。若是沒有傳遞任何開始命令給service,那將獲取到null的intent。

  2. START_NOT_STICKY
    在運行onStartCommand後service進程被kill後,而且沒有新的intent傳遞給它。Service將移出開始狀態,而且直到新的明顯的方法(startService)調用才從新建立。由於若是沒有傳遞任何未決定的intent那麼service是不會啓動,也就是期間onstartCommand不會接收到任何null的intent。

  3. START_REDELIVER_INTENT
    在運行onStartCommand後service進程被kill後,系統將會再次啓動service,並傳入最後一個intent給onstartCommand。直到調用stopSelf(int)才中止傳遞intent。若是在被kill後還有未處理好的intent,那被kill後服務仍是會自動啓動。所以onstartCommand不會接收到任何null的intent。

2、提高service優先級

在AndroidManifest.xml文件中對於intent-filter能夠經過android:priority = "1000"這個屬性設置最高優先級,1000是最高值,若是數字越小則優先級越低,同時適用於廣播。

3、提高service進程優先級

Android中的進程是託管的,當系統進程空間緊張的時候,會依照優先級自動進行進程的回收。Android將進程分爲6個等級,它們按優先級順序由高到低依次是:

  1. 前臺進程( FOREGROUND_APP)
  2. 可視進程(VISIBLE_APP )
  3. 次要服務進程(SECONDARY_SERVER )
  4. 後臺進程 (HIDDEN_APP)
  5. 內容供應節點(CONTENT_PROVIDER)
  6. 空進程(EMPTY_APP)

當service運行在低內存的環境時,將會kill掉一些存在的進程。所以進程的優先級將會很重要,可使用startForeground 將service放到前臺狀態。這樣在低內存時被kill的概率會低一些。

4、onDestroy方法裏重啓service

service +broadcast 方式,就是當service走ondestory的時候,發送一個自定義的廣播,當收到廣播的時候,從新啓動service;

5、Application加上Persistent屬性

6、監聽系統廣播判斷Service狀態

經過系統的一些廣播,好比:手機重啓、界面喚醒、應用狀態改變等等監聽並捕獲到,而後判斷咱們的Service是否還存活,別忘記加權限啊。

12.Android動畫框架實現原理

Animation框架定義了透明度,旋轉,縮放和位移幾種常見的動畫,並且控制的是整個View,實現原理是每次繪製視圖時View所在的ViewGroup中的drawChild函數獲取該View的Animation的Transformation值,而後調用canvas.concat(transformToApply.getMatrix()),經過矩陣運算完成動畫幀,若是動畫沒有完成,繼續調用invalidate()函數,啓動下次繪製來驅動動畫,動畫過程當中的幀之間間隙時間是繪製函數所消耗的時間,可能會致使動畫消耗比較多的CPU資源,最重要的是,動畫改變的只是顯示,並不能相應事件

13.Android爲每一個應用程序分配的內存大小是多少-美團

android程序內存通常限制在16M,也有的是24M。近幾年手機發展較快,通常都會分配兩百兆左右,和具體機型有關


14.優化自定義view百度-樂視-小米

爲了加速你的view,對於頻繁調用的方法,須要儘可能減小沒必要要的代碼。先從onDraw開始,須要特別注意不該該在這裏作內存分配的事情,由於它會致使GC,從而致使卡頓。在初始化或者動畫間隙期間作分配內存的動做。不要在動畫正在執行的時候作內存分配的事情。

你還須要儘量的減小onDraw被調用的次數,大多數時候致使onDraw都是由於調用了invalidate().所以請儘可能減小調用invaildate()的次數。若是可能的話,儘可能調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會強制重繪整個view。

另一個很是耗時的操做是請求layout。任什麼時候候執行requestLayout(),會使得Android UI系統去遍歷整個View的層級來計算出每個view的大小。若是找到有衝突的值,它會須要從新計算好幾回。另外須要儘可能保持View的層級是扁平化的,這樣對提升效率頗有幫助。

若是你有一個複雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操做。與內置的view不一樣,自定義的view可使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結構來計算大小。這個PieChart 例子展現瞭如何繼承ViewGroup做爲自定義view的一部分。PieChart 有子views,可是它歷來不測量它們。而是根據他自身的layout法則,直接設置它們的大小。

15.Android屬性動畫特性-樂視-小米

若是你的需求中只須要對View進行移動、縮放、旋轉和淡入淡出操做,那麼補間動畫確實已經足夠健全了。可是很顯然,這些功能是不足以覆蓋全部的場景的,一旦咱們的需求超出了移動、縮放、旋轉和淡入淡出這四種對View的操做,那麼補間動畫就不能再幫咱們忙了,也就是說它在功能和可擴展方面都有至關大的侷限性,那麼下面咱們就來看看補間動畫所不能勝任的場景。

注意上面我在介紹補間動畫的時候都有使用「對View進行操做」這樣的描述,沒錯,補間動畫是隻可以做用在View上的。也就是說,咱們能夠對一個Button、TextView、甚至是LinearLayout、或者其它任何繼承自View的組件進行動畫操做,可是若是咱們想要對一個非View的對象進行動畫操做,抱歉,補間動畫就幫不上忙了。可能有的朋友會感到不能理解,我怎麼會須要對一個非View的對象進行動畫操做呢?這裏我舉一個簡單的例子,好比說咱們有一個自定義的View,在這個View當中有一個Point對象用於管理座標,而後在onDraw()方法當中就是根據這個Point對象的座標值來進行繪製的。也就是說,若是咱們能夠對Point對象進行動畫操做,那麼整個自定義View的動畫效果就有了。顯然,補間動畫是不具有這個功能的,這是它的第一個缺陷。

而後補間動畫還有一個缺陷,就是它只可以實現移動、縮放、旋轉和淡入淡出這四種動畫操做,那若是咱們但願能夠對View的背景色進行動態地改變呢?很遺憾,咱們只能靠本身去實現了。說白了,以前的補間動畫機制就是使用硬編碼的方式來完成的,功能限定死就是這些,基本上沒有任何擴展性可言。

最後,補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?好比說,如今屏幕的左上角有一個按鈕,而後咱們經過補間動畫將它移動到了屏幕的右下角,如今你能夠去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,由於實際上這個按鈕仍是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪製到了屏幕的右下角而已。

16.Activity Window View三者的差異,fragment的特色-360

Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖)
LayoutInflater像剪刀,Xml配置像窗花圖紙。

  1. 在Activity中調用attach,建立了一個Window
  2. 建立的window是其子類PhoneWindow,在attach中建立PhoneWindow
  3. 在Activity中調用setContentView(R.layout.xxx)
  4. 其中其實是調用的getWindow().setContentView()
  5. 調用PhoneWindow中的setContentView方法
  6. 建立ParentView:做爲ViewGroup的子類,實際是建立的DecorView(做爲FramLayout的子類)
  7. 將指定的R.layout.xxx進行填充,經過佈局填充器進行填充【其中的parent指的就是DecorView】
  8. 調用到ViewGroup
  9. 調用ViewGroup的removeAllView(),先將全部的view移除掉
  10. 添加新的view:addView()

Fragment 特色

  • Fragment能夠做爲Activity界面的一部分組成出現;
  • 能夠在一個Activity中同時出現多個Fragment,而且一個Fragment也能夠在多個Activity中使用;
  • 在Activity運行過程當中,能夠添加、移除或者替換Fragment;
  • Fragment能夠響應本身的輸入事件,而且有本身的生命週期,它們的生命週期會受宿主Activity的生命週期影響。

17.View刷新機制-百度-美團

由ViewRoot對象的performTraversals()方法調用draw()方法發起繪製該View樹,值得注意的是每次發起繪圖時,並不會從新繪製每一個View樹的視圖,而只會從新繪製那些「須要重繪」的視圖,View類內部變量包含了一個標誌位DRAWN,當該視圖須要重繪時,就會爲該View添加該標誌位。

調用流程 :

mView.draw()開始繪製,draw()方法實現的功能以下:

  1. 繪製該View的背景
  2. 爲顯示漸變框作一些準備操做(見5,大多數狀況下,不須要改漸變框)
  3. 調用onDraw()方法繪製視圖自己 (每一個View都須要重載該方法,ViewGroup不須要實現該方法)
  4. 調用dispatchDraw ()方法繪製子視圖(若是該View類型不爲ViewGroup,即不包含子視圖,不須要重載該方法)值得說明的是,ViewGroup類已經爲咱們重寫了dispatchDraw ()的功能實現,應用程序通常不須要重寫該方法,但能夠重載父類函數實現具體的功能。
相關文章
相關標籤/搜索