首頁  >  文章  >  web前端  >  Android開發者面試阿里等大廠遇到的問題整理

Android開發者面試阿里等大廠遇到的問題整理

藏色散人
藏色散人轉載
2020-07-31 14:14:584016瀏覽

推薦:《2020年Android面試題大總結【收藏】

先簡單說說我這四年期間的面試經驗吧。面試的公司很多,其中有讓我心血沸騰的經歷,也有讓我感到失望到無助的經歷,我將這些體會都記錄下來,細想之後很值得,面了這麼多公司,要是最後什麼也沒有留下來,那就太浪費了。至少對我來說有些東西在整理總結之後才能得到一個肯定的答案。希望這些能對即將換工作或打算看看機會的你有一些幫助。

以下問題的答案均是個人四年來多次面試實踐中整理的,如有不同意見,歡迎斧正。

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

答案:

#一般非靜態內部類別持有外部類別的參考的情況下,造成外部類別在使用完成後不能被系統回收內存,從而造成內存洩漏。為了避免這個問題,我們可以自訂的Handler聲明為靜態內部類別形式,然後透過弱引用的方式,讓Handler持有外部類別的引用,從而避免記憶體洩漏問題。

以下是程式碼實作

public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView mTextView;
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 != null) {
                    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);
}
}复制代码

參考博文blog.csdn.net/ucxiii/arti…

2.onNewIntent()的呼叫時機

#解析:

在Android應用程式開發的時候,從一個Activity啟動另一個Activity並傳遞一些資料到新的Activity上非常簡單,但是當您需要讓後台運行的Activity回到前台並傳遞一些數據可能就會存在一點點小問題。

首先,在預設情況下,當您透過Intent啟到一個Activity的時候,就算已經存在一個相同的正在運行的Activity,系統都會建立一個新的Activity實例並顯示出來。為了不讓Activity實例化多次,我們需要透過在AndroidManifest.xml配置activity的載入方式(launchMode)以實現單一任務模式,如下所示:

6b4b8de82f5ec1f2a7986e15ef3b7143
abedf4926b16e78349669730db0843a2复制代码

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方法

以下是程式碼實例

1.設定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>复制代码

2.MainActivity中重寫onNewIntent方法

package code.xzy.com.handlerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
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....");
}
}复制代码

#3.Main2Actvity執行點擊跳轉,MainActivity被復用,執行onNewIntent方法

package code.xzy.com.handlerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
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中自己去提供回呼############### ##

jcodecraeer.com/a/anzhuokai… blog.csdn.net/lmj62356579… www.360doc.com/content/16/…

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的操作

6.HTTPS中SSL憑證認證的過程

7.簡述Android的Activity的內部機制

8.對Android Framework層的某一個模組(或System App)做簡單介紹

9.Android Handler的機制和原理

主執行緒使用Handler的過程

首先在主執行緒建立一個Handler對象,並重寫handleMessage()方法。然後當在子執行緒中需要進行更新UI的操作,我們就建立一個Message對象,並透過handler發送這則訊息出去。之後這則訊息被加入到MessageQueue佇列中等待被處理,透過Looper物件會一直嘗試從Message Queue中取出待處理的訊息,最後分發會Handler的handler Message()方法。

參考 blog.csdn.net/u012827296/…

10.執行緒間通訊和進程間通訊有什麼不同,Android開發過程中是怎麼實現的

www .cnblogs.com/yangtao1995…

11.簡述專案中對於記憶體最佳化的幾個細節點

答案:

  1. 當查詢完資料庫之後,及時關閉Cursor物件。
  2. 記得在Activity的onPause方法中呼叫unregisterReceiver()方法,反註冊廣播
  3. 避免Content記憶體洩漏,例如在4.0.1之前的版本上不要講Drawer物件置為static。當一個Drawable綁定到了View上,實際上這個View物件就會成為這個Drawable的一個callback成員變量,上面的例子中靜態的sBackground持有TextView物件lable的引用,而lable只有Activity的引用,而Activity會持有其他更多物件的引用。 sBackground生命週期要長於Activity。當螢幕旋轉時,Activity無法被銷毀,這樣就產生了記憶體外洩問題。
  4. 盡量不要在Activity中使用非靜態內部類,因為非靜態內部類別會隱式持有外部類別實例的引用,當非靜態內部類別的引用的聲明週期長於Activity的聲明週期時,會導致Activity無法被GC正常回收。
  5. 謹慎使用線程Thread! !這條是很多人會犯的錯誤: Java中的Thread有一個特點就是她們都是直接被GC Root所引用,也就是說Dalvik虛擬機對所有被激活狀態的線程都是持有強引用,導致GC永遠無法回收這些執行緒對象,除非執行緒被手動停止並置為null或使用者直接kill進程操作。所以當使用線程時,一定要考慮在Activity退出時,及時將線程也停止並釋放掉
  6. 使用Handler時,要么是放在單獨的類別文件中,要么就是使用靜態內部類別。因為靜態的內部類別不會持有外部類別的引用,所以不會導致外部類別實例的記憶體外洩

#12.簡述Android的視圖層級最佳化,簡述自訂View或自定義ViewGroup的步驟

個人的理解是,Android視圖渲染必須經過measure、layout、draw三個步驟,measure過程是在一個樹形結構中不斷遍歷的,如果UI層級嵌套很深,必將花費大量的時間,所以應該盡量減少層級嵌套,確保樹的結構扁平,並移除不需要渲染的views

自訂view步驟:

#Android自訂View的一般步驟

13.選取一個常用的第三方開源程式庫,簡述其存取步驟

Volley教學 blog.csdn.net/jdfkldjlkjd…

14.TCP與UPD的差異以及使用情境

TCP與UDP基本差異

  1. 基於連線與無連線
  2. TCP要求系統資源較多,UDP較少;
  3. UDP程式結構較簡單
  4. 串流模式(TCP)與資料封包模式(UDP);
  5. ##TCP保證資料正確性,UDP可能丟包
  6. TCP保證資料順序,UDP不保證

UDP應用程式場景:

##面向資料報方式

網路資料大多為短訊息

擁有大量Client

#對資料安全性無特殊要求網路負擔非常重,但對響應速度要求高

  1. 15.簡述一個設計模式的概念,並簡要談談framework層哪些地方用到了什麼設計模式
  2. 單例模式:單例模式是一種物件建立模式,它用於產生一個物件的特定實例,它可以確保系統中一個類別只產生一個實例。
適配器模式:將一個介面轉換成客戶希望的另一個接口,適配器模式使接口不相容的那些類別可以一起工作,其別名為包裝器(Wrapper)

裝飾模式:動態地為一個物件增加一些額外的職責,就增加物件功能來說,裝飾模式比產生子類別實作更為靈活。裝飾模式是一種物件結構型模式。

使用場景:

在不影響其他物件的情況下,以動態、透明的方式為單一物件新增職責。 當不能採用繼承的方式來擴充系統或採用繼承不利於系統擴充和維護時可以使用裝飾模式。

優點:

對於擴展一個物件的功能,裝飾模式比繼承更靈活,不會導致類別的數量急劇增加。

可以透過一種動態地方式來擴充一個物件的功能。

可以對一個物件進行多次裝飾,透過使用不同的特定裝飾類別以及這些裝飾類別的排列組合。

#########實際運用:#########Android中Context類別的實作######外觀模式:主要目的在於讓外部減少與子系統內部多個模組的交互,從而讓外部更簡單得使用子系統。它負責把客戶端的請求轉發給子系統內部的各個模組進行處理。 #########使用場景:######
  1. 當你要為一個複雜的子系統提供一個簡單的介面時
  2. 客戶程式與抽象類別的實作部分之前存在著很大的依賴性
  3. 當你需要建構一個層次結構的子系統時

**組合模式:**將物件以樹狀結構組織起來,以達成」部分--整體」的層次結構,使得客戶端對單一物件和組合物件的使用具有一致性。

使用場景:

  1. 需要表示一個物件整體或部分層次
  2. 讓客戶端能夠忽略不同物件層次的變化

優點:

1.高層模組呼叫簡單 2.節點自由增加

**模板方法:**是透過一個演算法骨架,而將演算法中的步驟延遲到子類,這樣子類就可以複寫這些步驟的實現來實現特定的演算法。

它的使用場景:

  1. 多個子類別有公有的方法,並且邏輯基本上相同
  2. 重要、複雜的演算法,可以把核心演算法設計為模板方法、
  3. 重構時,模板方法模式是常用的模式

觀察者模式:定義物件之間一種一對多依賴關係,使得每當一個物件狀態改變時,其相關依賴物件皆會被通知並被自動更新。

其使用場景:

  1. 一個抽像模型有兩個方面,其中一個方面依賴於另一個方面
  2. 一個物件的改變將導致一個或多個其他物件也發生改變
  3. 需要在系統中建立一個觸發鏈

具體應用:

例如在回呼模式中,實作了抽象類別/介面的實例實作了父類別提供的抽象方法後,將該方法交還給父類別來處理

Listview中的notifyDataSetChanged

#RxJava中的觀察者模式

**責任鏈模式:**是一個請求有多個物件來處理,這些物件是一條鏈,但具體由哪個物件來處理,根據條件判斷來決定,如果不能處理會傳遞給該鏈條中的下一個對象,直到有物件處理它為止。

使用場景:1.有多個物件可以處理同一個請求,具體哪個物件處理該請求待運行時再確定 2.在不明確指定接收者的情況下,向多個物件中的一個提交一個請求。

實際運用:Try...catch語句 OrderedBroadcast MotionEvent:actionDwon actionMove actionUp 事件分發機制三個重要方法:dispatchTouchEvent. onInterceptTouchEvent. onTouchEvent

**策略模式:**定義一系列的演算法,把它們一個個封裝起來,並且使他們可互相替換。本模式使得演算法可獨立於使用它的客戶而變化。策略模式的使用場景:一個類別定義了多種行為,並且這些行為在這個類別的方法中以多個條件語句的形式出現,那麼可以使用策略模式避免在類別中使用大量的條件語句。

使用場景:一個類別定義了多種行為,並且這些行為在這個類別的方法中以多個條件語句的形式出現,那麼可以使用策略模式避免在類別中使用大量的條件語句。

優點:1.上下文Context和具體策略ConcreateStrategy是鬆散耦合關係 2.策略模式滿足開-閉原則

具體應用:

  1. HttpStack
  2. Volley框架

16.位元組流和字元流的區別

位元組流操作的基本單元為位元組;字元流操作的基本單元為Unicode碼元(2個位元組)。 位元組流預設不使用緩衝區;字元流使用緩衝區。

位元組流通常用於處理二進位數據,實際上它可以處理任意類型的數據,但它不支援直接寫入或讀取Unicode碼元;字元流通常處理文字數據,它支援寫入及讀取Unicode碼元。

參考理解Java中字元流與位元組流的差異

17.View的繪製流程,是先測量父View還是先測量子View

#View與ViewGroup的基本繪製流程

18.OOM異常是否可以被try...catch捕獲(或者可否用try-catch捕獲Out Of Memory Error以避免其發生?)

只有在一種情況下,這樣做是可行的:在try語句中聲明了很大的對象,導致OOM,並且可以確認OOM是由try語句中的對象聲明導致的,那麼在catch語句中,可以釋放掉這些對象,解決OOM的問題,繼續執行剩餘語句。

但這通常不是合適的做法。 Java中管理記憶體除了明確地catch OOM之外還有更多有效的方法:例如SoftReference, WeakReference, 硬碟快取等。在JVM用光記憶體之前,會多次觸發GC,這些GC會降低程式運作的效率。如果OOM的原因不是try語句中的物件(例如記憶體洩漏),那麼在catch語句中會繼續拋出OOM

19.WeakReference和SoftReference的差異

#Java的StrongReference, SoftReference , WeakReference, PhantomReference的區別

20.請計算一張100像素*100像素的圖片所佔用記憶體

blog.csdn.net/u010652002/…

21.okHttp實作的原理

22.okHttp有哪些攔截器

23.計算1 2! 3! 4! 5! ... 20!的結果,用程式碼實作

24.寫出單例模式,哪些是執行緒安全的,為什麼是執行緒安全的

25.Retrofit實作原理

26.android圖片有哪些格式

答案:blog.csdn.net/xmc28114194…

27.sqlite可以執行多執行緒操作嗎?如何保證多執行緒操作資料庫的安全性愛

答案:

每當你需要使用資料庫時,你需要使用DatabaseManager的openDatabase()方法來取得資料庫,這個方法裡面使用了單例模式,保證了資料庫物件的唯一性,也就是每次操作資料庫時所使用的sqlite物件都是一致得到。其次,我們會使用一個引用計數來判斷是否要建立資料庫物件。如果引用計數為1,則需要建立一個資料庫,如果不為1,表示我們已經建立過了。 在closeDatabase()方法中我們同樣透過判斷引用計數的值,如果引用計數降為0,則表示我們需要close資料庫。

大致的做法就是在多執行緒存取的情況下需要自己來封裝一個DatabaseManager來管理Sqlite資料庫的讀寫,需要同步的同步,需要非同步的非同步,不要直接操作資料庫,這樣很容易出現因為鎖的問題導致加鎖後的操作失敗。

答案參考了這篇文章blog.csdn.net/rockcode_li…

28.有兩個長度已知的鍊錶,怎麼決定兩個鍊錶的交集

解析:leetcode 兩個鍊錶的交集點 www.360doc.com/content/16/…

有以下幾種想法:

(1) 暴力破解,遍歷鍊錶A的所有節點,並且對於每個節點,都與鍊錶B中的所有節點比較,退出條件是在B中找到第一個相等的節點。時間複雜度O(lengthA*lengthB),空間複雜度O(1)。

(2) 哈希表 。遍歷鍊錶A,並且將節點儲存到哈希表中。接著遍歷鍊錶B,對於B中的每個節點,找出哈希表,如果在雜湊表中找到了,表示是交集開始的那個節點。時間複雜度O(lengthA lengthB),空間複雜度O(lengthA)或O(lengthB)。

(3) 雙指標法 ,指標pa、pb分別指向鍊錶A和B的首節點。

遍歷鍊錶A,記錄其長度lengthA,遍歷鍊錶B,記錄其長度lengthB。

因為兩個鍊錶的長度可能不相同,例如題目所給的case,lengthA=5,lengthB=6,則作差得到lengthB- lengthA=1,將指標pb從鍊錶B的首節點開始走1步,即指向了第二個節點,pa指向鍊錶A首節點,然後它們同時走,每次都走一步,當它們相等時,就是交集的節點。

結尾

如今安卓開發不像前幾年那麼熱門,但是高級人才依然緊缺,大家看著這句話是不是很熟悉,因為web 高級人才也緊缺,c 高級人才一樣緊缺,那麼到了人工智慧時代,人工智慧時代的高級人才也同樣會緊缺! 似乎是高級人才的人在其他領域也是高級人才,而不是因為選擇了熱門才會一帆風順。

網路上資深工程師面試相關文章魚龍混雜,要嘛一堆內容,要嘛內容品質太淺, 鑑於此我整理瞭如下安卓開發高級工程師面試題以及答案幫助大家順利進階為高級工程師,目前我任職於某大廠安卓高級工程師職位,在當下大環境下也想為安卓工程師出一份力,這些問題都是我認真看過並且覺得不錯才整理出來,大家知道高階工程師不會像剛入門那樣被問到的問題一句話兩句話就能表述清楚,所以我透過過濾好文章來幫助大家理解,希望對大家有幫助。

以上是Android開發者面試阿里等大廠遇到的問題整理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除