天天看點

月薪20k的Android面試都問這些問題(含答案)

金三銀四跳槽季即将過完,相信大家肯定急需一套Android面試寶典,今天給大家準備了我珍藏已久的Android高階面試寶典,供大家學習 !【文末有幹貨】

月薪20k的Android面試都問這些問題(含答案)

一、面試題:

1.自定義Handler時如何避免記憶體洩漏

2.onNewIntent的調用時機

3.RecyclerView相比ListView有哪些優勢

4.談一談Proguard混淆技術

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

二、詳細解析:

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回到前台并傳遞一些資料可能就會存在一點點小問題。

首先,在預設情況下,當您通過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方法

前提:ActivityA已經啟動過,處于目前應用的Activity堆棧中;當ActivityA的LaunchMode為SingleTop時,如果ActivityA在棧頂,且現在要再啟動ActivityA,這時會調用onNewIntent方法
當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中自己去提供回調

月薪20k的Android面試都問這些問題(含答案)

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的操作
月薪20k的Android面試都問這些問題(含答案)

這些是小編根據上面的進階工程師技術大綱整理的一套系統全面而且非常深入的Android進階資料

月薪20k的Android面試都問這些問題(含答案)
月薪20k的Android面試都問這些問題(含答案)

這些資料都可以免費分享給大家!點選連結加入群聊【騰訊@Android進階架構】歡迎大家進群,領取資料,一起學習交流!

命運永遠會眷顧那些努力付出的人。如果你還沒達到你的目标,那是因為你努力的程度還不夠!

希望看到最後的朋友們,通過一年到兩年的努力,都能實作追求的目标。

繼續閱讀