最全Android面試大綱(二)【含答案】

Android優(yōu)化工具

TraceView

raceview 是Android SDK中自帶的一個(gè)工具,可以 對(duì)應(yīng)用中方法調(diào)用耗時(shí)進(jìn)行統(tǒng)計(jì)分析,是Android性能優(yōu)化和分析時(shí)一個(gè)很重要的工具。使用方法:第一種是在相應(yīng)進(jìn)行traceview分析的開始位置和結(jié)束位置分別調(diào)用startMethodTracing和stopMethodTracing方法。第二種是在ddms中直接使用,即在ddms中在選中某個(gè)要進(jìn)行監(jiān)控的進(jìn)程后,點(diǎn)擊如圖所示的小圖標(biāo)開始監(jiān)控,在監(jiān)控結(jié)束時(shí)再次點(diǎn)擊小圖標(biāo),ddms會(huì)自動(dòng)打開traceview視圖。

Systrace

Systrace是Android4.1中新增的性能數(shù)據(jù)采樣和分析工具。它可幫助開發(fā)者收集Android關(guān)鍵子系統(tǒng)(如surfaceflinger、WindowManagerService等Framework部分關(guān)鍵模塊、服務(wù))的運(yùn)行信息,從而幫助開發(fā)者更直觀的分析系統(tǒng)瓶頸,改進(jìn)性能。

Systrace的功能包括跟蹤系統(tǒng)的I/O操作、內(nèi)核工作隊(duì)列、CPU負(fù)載以及Android各個(gè)子系統(tǒng)的運(yùn)行狀況等。

Dalvik與ART的區(qū)別?

Dalvik是Google公司自己設(shè)計(jì)用于Android平臺(tái)的Java虛擬機(jī)。Dalvik虛擬機(jī)是Google等廠商合作開發(fā)的Android移動(dòng)設(shè)備平臺(tái)的核心組成部分之一,它可以支持已轉(zhuǎn)換為.dex(即Dalvik Executable)格式的Java應(yīng)用程序的運(yùn)行,.dex格式是專為Dalvik應(yīng)用設(shè)計(jì)的一種壓縮格式,適合內(nèi)存和處理器速度有限的系統(tǒng)。Dalvik經(jīng)過優(yōu)化,允許在有限的內(nèi)存中同時(shí)運(yùn)行多個(gè)虛擬機(jī)的實(shí)例,并且每一個(gè)Dalvik應(yīng)用作為獨(dú)立的Linux進(jìn)程執(zhí)行。獨(dú)立的進(jìn)程可以防止在虛擬機(jī)崩潰的時(shí)候所有程序都被關(guān)閉。

ART代表Android Runtime,其處理應(yīng)用程序執(zhí)行的方式完全不同于Dalvik,Dalvik是依靠一個(gè)Just-In-Time(JIT)編譯器去解釋字節(jié)碼。開發(fā)者編譯后的應(yīng)用代碼需要通過一個(gè)解釋器在用戶的設(shè)備上運(yùn)行,這一機(jī)制并不高效,但讓應(yīng)用能更容易在不同硬件和架構(gòu)上運(yùn)行。ART則完全改變了這套做法,在應(yīng)用安裝的時(shí)候就預(yù)編譯字節(jié)碼到機(jī)器語言,這一機(jī)制叫 Ahead-Of-Time(AOT) 編譯 。在移除解釋代碼這一過程后,應(yīng)用程序執(zhí)行將更有效率,啟動(dòng)更快。

ART優(yōu)點(diǎn):
  1. 系統(tǒng)性能的顯著提升
  2. 應(yīng)用啟動(dòng)更快、運(yùn)行更快、體驗(yàn)更流暢、觸感反饋更及時(shí)
  3. 更長(zhǎng)的電池續(xù)航能力
    4.支持更低的硬件
ART缺點(diǎn):
  1. 更大的存儲(chǔ)空間占用,可能會(huì)增加10%-20%
  2. 更長(zhǎng)的應(yīng)用安裝時(shí)間

Android動(dòng)態(tài)權(quán)限?

Android 6.0 動(dòng)態(tài)權(quán)限,這里以撥打電話的權(quán)限為例,首先需要在Manifest里添加android.permission.CALL_PHONE權(quán)限。

int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);
    if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
                this, new String[]{Manifest.permission.CALL_PHONE}, REQUEST_CODE_ASK_CALL_PHONE);
        return;
    }
    ```
    在獲取權(quán)限后,可以重寫Activity.onRequestPermissionsResult方法來進(jìn)行回調(diào)。
    ```
    @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    switch (requestCode) {
        case REQUEST_CODE_ASK_CALL_PHONE:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission Granted
                Toast.makeText(MainActivity.this, "CALL_PHONE Granted", Toast.LENGTH_SHORT)
                        .show();
            } else {
                // Permission Denied
                Toast.makeText(MainActivity.this, "CALL_PHONE Denied", Toast.LENGTH_SHORT)
                        .show();
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

ViewPager如何判斷左右滑動(dòng)?

實(shí)現(xiàn)OnPageChangeListener并重寫onPageScrolled方法,通過參數(shù)進(jìn)行判斷。

ListView與RecyclerView

  1. ViewHolder:在ListView中,ViewHolder需要自己來定義,且這只是一種推薦的使用方式,不使用當(dāng)然也可以,這不是必須的。而在RecyclerView中使用 RecyclerView.ViewHolder 則變成了必須,盡管實(shí)現(xiàn)起來稍顯復(fù)雜,但它卻解決了ListView面臨的上述不使用自定義ViewHolder時(shí)所面臨的問題。

  2. LayoutManager:RecyclerView提供了更加豐富的布局管理。LinearLayoutManager,可以支持水平和豎直方向上滾動(dòng)的列表。StaggeredGridLayoutManager,可以支持交叉網(wǎng)格風(fēng)格的列表,類似于瀑布流或者Pinterest。GridLayoutManager,支持網(wǎng)格展示,可以水平或者豎直滾動(dòng),如展示圖片的畫廊。

  3. ItemAnimator:相比較于ListView,RecyclerView.ItemAnimator 則被提供用于在RecyclerView添加、刪除或移動(dòng)item時(shí)處理動(dòng)畫效果。

  4. ItemDecoration:RecyclerView在默認(rèn)情況下并不在item之間展示間隔符。如果你想要添加間隔符,你必須使用RecyclerView.ItemDecoration類來實(shí)現(xiàn)。

ListView可以設(shè)置選擇模式,并添加MultiChoiceModeListener,RecyclerView中并沒有提供這樣功能。

SpannableString

TextView通常用來顯示普通文本,但是有時(shí)候需要對(duì)其中某些文本進(jìn)行樣式、事件方面的設(shè)置。Android系統(tǒng)通過SpannableString類來對(duì)指定文本進(jìn)行相關(guān)處理??梢酝ㄟ^SpannableString來對(duì)TextView進(jìn)行富文本設(shè)置,包括但不限于文本顏色,刪除線,圖片,超鏈接,字體樣式

描述一下Android手機(jī)啟動(dòng)過程和App啟動(dòng)過程?

Android手機(jī)啟動(dòng)過程

當(dāng)我們開機(jī)時(shí),首先是啟動(dòng)Linux內(nèi)核,在Linux內(nèi)核中首先啟動(dòng)的是init進(jìn)程,這個(gè)進(jìn)程會(huì)去讀取配置文件system\core\rootdir\init.rc配置文件,這個(gè)文件中配置了Android系統(tǒng)中第一個(gè)進(jìn)程Zygote進(jìn)程。

啟動(dòng)Zygote進(jìn)程 --> 創(chuàng)建AppRuntime(Android運(yùn)行環(huán)境) --> 啟動(dòng)虛擬機(jī) --> 在虛擬機(jī)中注冊(cè)JNI方法 --> 初始化進(jìn)程通信使用的Socket(用于接收AMS的請(qǐng)求) --> 啟動(dòng)系統(tǒng)服務(wù)進(jìn)程 --> 初始化時(shí)區(qū)、鍵盤布局等通用信息 --> 啟動(dòng)Binder線程池 --> 初始化系統(tǒng)服務(wù)(包括PMS,AMS等等) --> 啟動(dòng)Launcher

App啟動(dòng)過程
在這里插入圖片描述
  1. 應(yīng)用的啟動(dòng)是從其他應(yīng)用調(diào)用startActivity開始的。通過代理請(qǐng)求AMS啟動(dòng)Activity。

  2. AMS創(chuàng)建進(jìn)程,并進(jìn)入ActivityThread的main入口。在main入口,主線程初始化,并loop起來。主線程初始化,主要是實(shí)例化ActivityThread和ApplicationThread,以及MainLooper的創(chuàng)建。ActivityThread和ApplicationThread實(shí)例用于與AMS進(jìn)程通信。

  3. 應(yīng)用進(jìn)程將實(shí)例化的ApplicationThread,Binder傳遞給AMS,這樣AMS就可以通過代理對(duì)應(yīng)用進(jìn)程進(jìn)行訪問。

  4. AMS通過代理,請(qǐng)求啟動(dòng)Activity。ApplicationThread通知主線程執(zhí)行該請(qǐng)求。然后,ActivityThread執(zhí)行Activity的啟動(dòng)。

  5. Activity的啟動(dòng)包括,Activity的實(shí)例化,Application的實(shí)例化,以及Activity的啟動(dòng)流程:create、start、resume。

可以看到 入口Activity其實(shí)是先于Application實(shí)例化,只是onCreate之類的流程,先于Activity的流程。另外需要scheduleLaunchActivity,在ApplicationThreaad中,對(duì)應(yīng)AMS管理Activity生命周期的方法都以scheduleXXXActivity,ApplicationThread在Binder線程中,它會(huì)向主線程發(fā)送消息,ActivityThread的Handler會(huì)調(diào)用相應(yīng)的handleXXXActivity方法,然后會(huì)執(zhí)行performXXXActivity方法,最終調(diào)用Activity的onXXX方法

Include、Merge、ViewStub的作用

Include:布局重用
  • <include />標(biāo)簽可以使用單獨(dú)的layout屬性,這個(gè)也是必須使用的。

  • 可以使用其他屬性。<include />標(biāo)簽若指定了ID屬性,而你的layout也定義了ID,則你的layout的ID會(huì)被覆蓋,解決方案。

  • 在<include />標(biāo)簽中所有的android:layout_*都是有效的,前提是必須要寫layout_width和layout_height兩個(gè)屬性。

  • 布局中可以包含兩個(gè)相同的include標(biāo)簽

Merge:減少視圖層級(jí),多用于替換FrameLayout或者當(dāng)一個(gè)布局包含另一個(gè)時(shí),<merge/>標(biāo)簽消除視圖層次結(jié)構(gòu)中多余的視圖組。

例如:你的主布局文件是垂直布局,引入了一個(gè)垂直布局的include,這是如果include布局使用的LinearLayout就沒意義了,使用的話反而減慢你的UI表現(xiàn)。這時(shí)可以使用標(biāo)簽優(yōu)化。

ViewStub:需要時(shí)使用。優(yōu)點(diǎn)是當(dāng)你需要時(shí)才會(huì)加載,使用他并不會(huì)影響UI初始化時(shí)的性能。需要使用時(shí)調(diào)用inflate()。

Asset目錄與res目錄的區(qū)別

  • assets 目錄:不會(huì)在R.java文件下生成相應(yīng)的標(biāo)記,assets文件夾可以自己創(chuàng)建文件夾,必須使用AssetsManager類進(jìn)行訪問,存放到這里的資源在運(yùn)行打包的時(shí)候都會(huì)打入程序安裝包中,

  • res 目錄:會(huì)在R.java文件下生成標(biāo)記,這里的資源會(huì)在運(yùn)行打包操作的時(shí)候判斷哪些被使用到了,沒有被使用到的文件資源是不會(huì)打包到安裝包中的。

res/raw 和 assets文件夾來存放不需要系統(tǒng)編譯成二進(jìn)制的文件,例如字體文件等

res/raw不可以有目錄結(jié)構(gòu),而assets則可以有目錄結(jié)構(gòu),也就是assets目錄下可以再建立文件夾

System.gc && Runtime.gc

System.gc和Runtime.gc是等效的,在System.gc內(nèi)部也是調(diào)用的Runtime.gc。調(diào)用兩者都是通知虛擬機(jī)要進(jìn)行g(shù)c,但是否立即回收還是延遲回收由JVM決定。兩者唯一的區(qū)別就是一個(gè)是類方法,一個(gè)是實(shí)例方法。

Application 在多進(jìn)程下會(huì)多次調(diào)用 onCreate() 么?

當(dāng)采用多進(jìn)程的時(shí)候,比如下面的Service 配置:

<service
    android:name=".MyService"
    android:enabled="true"
    android:exported="false"
    android:process=":remote" />

android:process 屬性中 :的作用就是把這個(gè)名字附加到你的包所運(yùn)行的標(biāo)準(zhǔn)進(jìn)程名字的后面作為新的進(jìn)程名稱。

這樣配置會(huì)調(diào)用 onCreate() 兩次。

Theme && Style

Style 是一組外觀、樣式的屬性集合,適用于 View 和 Window 。

Theme 是一種應(yīng)用于整個(gè) Activity 或者 Application ,而不是獨(dú)立的 View。

SQLiteOpenHelper.onCreate() 調(diào)用時(shí)機(jī)?

在調(diào)getReadableDatabase或getWritableDatabase時(shí),會(huì)判斷指定的數(shù)據(jù)庫是否存在,不存在則調(diào)SQLiteDatabase.onCreate創(chuàng)建, onCreate只在數(shù)據(jù)庫第一次創(chuàng)建時(shí)才執(zhí)行。

Removecallback 失效?

Removecallback 必須是同一個(gè)Handler才能移除。

Toast 如果會(huì)短時(shí)間內(nèi)頻繁顯示怎么優(yōu)化?

public void update(String msg){
  toast.setText(msg);
  toast.show();
}

Notification 如何優(yōu)化?

可以通過 相同 ID 來更新 Notification 。

應(yīng)用怎么判斷自己是處于前臺(tái)還是后臺(tái)?

主要是通過 getRunningAppProcesses() 方法來實(shí)現(xiàn)。

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
    if (appProcess.processName.equals(getPackageName())) {
        if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            Log.d(TAG, String.format("Foreground App:%s", appProcess.processName));
        } else {
            Log.d(TAG, "Background App:" + appProcess.processName);
        }
    }
}

FragmentPagerAdapter 和 FragmentStateAdapter 的區(qū)別?

FragmentStatePagerAdapter 是 PagerAdapter 的子類,這個(gè)適配器對(duì)實(shí)現(xiàn)多個(gè) Fragment 界面的滑動(dòng)是非常有用的,它的工作方式和listview是非常相似的。當(dāng)Fragment對(duì)用戶不可見的時(shí)候,整個(gè)Fragment會(huì)被銷毀,只會(huì)保存Fragment的保存狀態(tài)?;谶@樣的特性,F(xiàn)ragmentStatePagerAdapter 比 FragmentPagerAdapter 更適合用于很多界面之間的轉(zhuǎn)換,而且消耗更少的內(nèi)存資源。

Bitmap的本質(zhì)?

本質(zhì)是 SkBitmap 詳見 Pocket

SurfaceView && View && GLSurfaceView

  • View:顯示視圖,內(nèi)置畫布,提供圖形繪制函數(shù)、觸屏事件、按鍵事件函數(shù)等;必須在UI主線程內(nèi)更新畫面,速度較慢。

  • SurfaceView:基于view視圖進(jìn)行拓展的視圖類,更適合2D游戲的開發(fā);View的子類,類似使用雙緩機(jī)制,在新的線程(也可以在UI線程)中更新畫面所以刷新界面速度比 View 快,但是會(huì)涉及到線程同步問題。

GLSurfaceView:openGL專用?;赟urfaceView視圖再次進(jìn)行拓展的視圖類,專用于3D游戲開發(fā)的視圖。

文末送福利啦??!

我總結(jié)出了互聯(lián)網(wǎng)公司Android程序員面試涉及到的絕大部分面試題及答案,并整理做成了文檔,以及系統(tǒng)的進(jìn)階學(xué)習(xí)視頻資料,免費(fèi)分享給大家。
(包括Java在Android開發(fā)中應(yīng)用、APP框架知識(shí)體系、高級(jí)UI、全方位性能調(diào)優(yōu),NDK開發(fā),音視頻技術(shù),人工智能技術(shù),跨平臺(tái)技術(shù)等技術(shù)資料),希望能幫助到你面試前的復(fù)習(xí),且找到一個(gè)好的工作,也節(jié)省大家在網(wǎng)上搜索資料的時(shí)間來學(xué)習(xí)。
資料領(lǐng)取方式:點(diǎn)擊鏈接加入群聊【Android開發(fā)交流】:https://jq.qq.com/?_wv=1027&k=57fcAxd,找群管理免費(fèi)領(lǐng)取。備注一下簡(jiǎn)書看到的來領(lǐ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)容

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