月薪20k+的Android面試都問些什麼(含答案)

你們確定急需一套Android面試寶典,今天給你們準備了我珍藏已久的Android高階面試寶典,供你們學習 !【文末有乾貨】 java

1、面試題:

1.自定義Handler時如何避免內存泄漏 2.onNewIntent的調用時機 3.RecyclerView相比ListView有哪些優點 4.談一談Proguard混淆技術 5.ANR出現的場景及解決方案android

2、詳細解析:

1.自定義Handler時如何避免內存泄漏

通常非靜態內部類持有外部類的引用的狀況下,形成外部類在使用完成後不能被系統回收內存,從而形成內存泄漏。爲了不這個問題,咱們能夠自定義的Handler聲明爲靜態內部類形式,而後經過弱引用的方式,讓Handler持有外部類的引用,從而可避免內存泄漏問題。面試

如下是代碼實現數據庫

private WeakReference < MainActivity > activityWeakReference;

private MyHandler myHandler;

static class MyHandler extends Handler {

    private MainActivity activity;

    MyHandler(WeakReference < MainActivity > ref) {

        this.activity = ref.get;

    }

    @Override

    public void handleMessage(Message msg) {

        super.handleMessage(msg);

        switch (msg.what) {

        case 1:

            //須要作判空操做
            if (activity != ) {

                activity.mTextView.setText("new Value");

            }

            break;

        default:

            Log.i(TAG, "handleMessage: default ");

            break;

        }

        @Override

        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            //在onCreate中初始化
            activityWeakReference = new WeakReference < MainActivity > (this);

            myHandler = new MyHandler(activityWeakReference);

            myHandler.sendEmptyMessage(1);

            mTextView = (TextView) findViewById(R.id.tv_test);

        }
複製代碼

2.onNewIntent的調用時機

在Android應用程序開發的時候,從一個Activity啓動另外一個Activity並傳遞一些數據到新的Activity上很是簡單,可是當您須要讓後臺運行的Activity回到前臺並傳遞一些數據可能就會存在一點點小問題。bash

首先,在默認狀況下,當您經過Intent啓到一個Activity的時候,就算已經存在一個相同的正在運行的Activity,系統都會建立一個新的Activity實例並顯示出來。爲了避免讓Activity實例化屢次,咱們須要經過在AndroidManifest.xml配置activity的加載方式(launchMode)以實現單任務模式,以下所示:網絡

<activity android:label="@string/app_name"

android:launchmode="singleTask"android:name="Activity1">

</activity>
複製代碼

launchMode爲singleTask的時候,經過Intent啓到一個Activity,若是系統已經存在一個實例,系統就會將請求發送到這個實例上,但這個時候,系統就不會再調用一般狀況下咱們處理請求數據的onCreate方法,而是調用onNewIntent方法app

前提:ActivityA已經啓動過,處於當前應用的Activity堆棧中;當ActivityA的LaunchMode爲SingleTop時,若是ActivityA在棧頂,且如今要再啓動ActivityA,這時會調用onNewIntent方法ide

當ActivityA的LaunchMode爲SingleInstance,SingleTask時,若是已經ActivityA已經在堆棧中,那麼此時會調用onNewIntent方法學習

當ActivityA的LaunchMode爲Standard時,因爲每次啓動ActivityA都是啓動新的實例,和原來啓動的不要緊,因此不會調用原來ActivityA的onNewIntent方法,仍然調用的是onCreate方法優化

如下是代碼實例

  • 設置MainActivity的啓動模式爲SingleTask(棧內複用)
<activity

android:name=".MainActivity"

android:launchMode="singleTask">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>
複製代碼
  • MainActivity中重寫onNewIntent方法
public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private Button mButton;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mButton = (Button) findViewById(R.id.forward_btn);

        mButton.setOnClickListener(new View.OnClickListener {

            @Override

            public void onClick(View view) {

                startActivity(new Intent(MainActivity.this, Main2Activity.class));

            }

        });

        @Override

        protected void onNewIntent(Intent intent) {

            Toast.makeText(this, "onnewIntent", Toast.LENGTH_SHORT).show;

            Log.i(TAG, "onNewIntent: i done....");

        }
複製代碼
  • Main2Actvity執行點擊跳轉,MainActivity被複用,執行onNewIntent方法
public class Main2Activity extends AppCompatActivity {

    private Button mButton;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main2);

        mButton = (Button) findViewById(R.id.btn);

        mButton.setOnClickListener(new View.OnClickListener {

            @Override

            public void onClick(View view) {

                startActivity(new Intent(Main2Activity.this, MainActivity.class));

                finish;

            }

        });
複製代碼

3.RecyclerView相比ListView有哪些優點

首先須要解釋下RecyclerView的這個名字了,從它類名上看,RecyclerView表明的意義是,我只管Recycler View,也就是說RecyclerView只管回收與複用View,其餘的你能夠本身去設置。能夠看出其高度的解耦,給予你充分的定製自由(因此你才能夠輕鬆的經過這個控件實現ListView,GirdView,瀑布流等效果)

其次RecyclerView提供了添加、刪除item的動畫 效果,並且能夠自定義

RecyclerView相比ListView優點在於能夠輕鬆實現:

  • ListView的功能
  • GridView的功能
  • 橫向ListView的功能
  • 橫向ScrollView的功能
  • 瀑布流效果
  • 便於添加Item增長和移除動畫 不過一個挺鬱悶的地方就是,系統沒有提供ClickListener和LongClickListener。

不過咱們也能夠本身去添加,只是會多了些代碼而已。

實現的方式比較多,你能夠經過mRecyclerView.addOnItemTouchListener去監聽而後去判斷手勢,

固然你也能夠經過adapter中本身去提供回調

4.談一談Proguard混淆技術

Proguard技術有以下功能:

  • 壓縮 --檢查並移除代碼中無用的類
  • 優化--對字節碼的優化,移除無用的字節碼
  • 混淆--混淆定義的名稱,避免反編譯
  • 預監測--在java平臺對處理後的代碼再次進行檢測

代碼混淆只在上線時纔會用到,debug模式下會關閉,是一種可選的技術。

那麼爲何要使用代碼混淆呢? 由於Java是一種跨平臺的解釋性開發語言,而java的源代碼會被編譯成字節碼文件,存儲在.class文件中,因爲跨平臺的須要,java的字節碼中包含了不少源代碼信息,諸如變量名、方法名等等。而且經過這些名稱來訪問變量和方法,這些變量不少是無心義的,可是又很容易反編譯成java源代碼,爲了防止這種現象,咱們就須要經過proguard來對java的字節碼進行混淆,混淆就是對發佈的程序進行從新組織和處理,使得處理後的代碼與處理前的代碼有相同的功能,和不一樣的代碼展現,即便被反編譯也很難讀懂代碼的含義,哪些混淆過的代碼仍能按照以前的邏輯執行獲得同樣的結果。

可是,某些java類是不能被混淆的,好比實現了序列化的java類是不能被混淆的,不然反序列化時會出問題。

下面這類代碼混淆的時候要注意保留,不能混淆。

  • Android系統組件,系統組件有固定的方法被系統調用。
  • 被Android Resource 文件引用到的。名字已經固定,也不能混淆,好比自定義的View 。
  • Android Parcelable ,須要使用android 序列化的。

其餘Anroid 官方建議 不混淆的,如

  • android.app.backup.BackupAgentHelper
  • android.preference.Preference
  • com.android.vending.licensing.ILicensingService
  • Java序列化方法,系統序列化須要固定的方法。
  • 枚舉 ,系統須要處理枚舉的固定方法。
  • 本地方法,不能修改本地方法名
  • annotations 註釋
  • 數據庫驅動
  • 有些resource 文件

5.ANR出現的場景及解決方案

在Android中,應用的響應性被活動管理器(Activity Manager)和窗口管理器(Window Manager)這兩個系統服務所監視。當用戶觸發了輸入事件(如鍵盤輸入,點擊按鈕等),若是應用5秒內沒有響應用戶的輸入事件,那麼,Android會認爲該應用無響應,便彈出ANR對話框。而彈出ANR異常,也主要是爲了提高用戶體驗。

解決方案是對於耗時的操做,好比訪問網絡、訪問數據庫等操做,須要開闢子線程,在子線程處理耗時的操做,主線程主要實現UI的操做

這些是木木根據上面的高級工程師技術大綱整理的一套系統全面並且很是深刻的Android進階資料和麪試題

下面是部分資料截圖

資料免費領取方式:如今關注我而且加入羣聊 羣號:1018342383 或者是點擊連接加入羣聊 【Android開發交流】:jq.qq.com/?_wv=1027&a…

相關文章
相關標籤/搜索