2019年的面試條目總結

MY就是我發表於2019-09-25

2019年的面試條目總結

一.熟練對Android Q版本適配

  1. 儲存沙箱化, 每個應用訪問自己沙箱內的檔案。訪問別的沙箱解決辦法類似於FileUriExposedException,用FileProvider將file轉換為content傳遞

  2. 裝置唯一id獲取,谷歌開放了新的裝置id獲取方式,目前不同手機獲取的方式不同以前的 READ_PHONE_STATE 方式變為了READ_PRIVILEGED_PHONE_STATE

  3. 非SDK介面的限制,設定禁止對非sdk介面的依賴,主要是一些第三方的熱修復,加固方案使用了這些被限制的SDK介面

  4. 限制了明文流量,只有使用https才可以訪問

二.安卓各版本的新特性

  1. Android 6.0(M) ,完整的許可權控制,危險許可權需要動態獲取。 API 檢測是否有授權,申請授權,許可權失敗解釋

  2. Android7.0 (N) , 刪除了三種靜態廣播 網路狀態新照片和新視訊

  3. Android8.0(P),自適應的圖示型別,推送和通知的管理

三.Glide原始碼解析

四.EventBus原始碼解析

五.Arouter原始碼解析

六.Retrofit原始碼解析

  1. Retrofit使用Retrofit.create(Class)方法建立出Service 介面物件,使retrofit可以在Service中進行引數配置

  2. 然而在Retrofit.create()方法中,是使用Proxy.newProxyInstance()方法來建立Service介面例項,這個例項實現了所有的介面方法,呼叫例項的InvocationHandler成員變數的invoke()方法,InvocationHandler物件就會代理介面中的是設定。

  3. invoke()中的邏輯:

    1. loadServiceMethod(method)將interface中的方法資訊讀取並初步分析生成ServiceMethod

    2. OkHttpCall<Object> okHttpCall = new OkhttpCall<>(serviceMethod,args)負責將ServiceMethod封裝到retrofit2.call物件,該物件在enqueue等的時候會呼叫okhttp.call物件,由它來進行網路請求的發起

    3. serviceMethod.adapt(okHttpCall) 中,serviceMethod裡面的的callAdapter物件把okHttpCall轉為新的retrofit.call型別物件。這個call中,後臺執行緒發起的請求的返回中,呼叫主執行緒回撥方法。還可以生成rxjava的Obervable等

七.Okhttp3原始碼解析

  1. 首先創造出一個OkhttpClient進行網路配置,然後建立一個Request傳入client,client建立一個call開始發起請求。

  2. Dispatcher dispatcher:排程器,排程後臺發起的網路請求,可設定主機請求數和後臺請求數

    List<Protocol> protocols:支援的應用層協議版本

    List<ConnectionSpec> connectionSpecs:應用層支援的Socket設定,即使用明文傳輸 還是TLS

    List<Interceptor> interceptors大多數的Interceptor都會配置在這裡

    List<Interceptor> networkInterceptors:直接和網路請求互動的Interceptor配置到這裡

    CookieJar cookieJar:管理Cookie的控制器,提供了基礎的存取判斷,剩下的需要自己實現

    Cache cache:Cache 儲存的配置。預設是沒有,如果需要⽤,得⾃⼰配置出 Cache 儲存的⽂件位置以及儲存空間上限。

    HostnameVerifier hostnameVerifier:⽤於驗證 HTTPS 握⼿過程中下載到的證照所屬者是否和⾃⼰要訪問的主機名⼀致。

    Authenticator[ɔːˈθɛntɪkeɪtə] authenticator:用於自動重新認證。配置後收到401時會直接呼叫authenticator,重新發起請求

  3. OKHttp3通過攔截鏈的設計,讓請求分成5個攔截器去處理,攔截器各司其職,擴充套件性非常高。攔截鏈是從自定義的攔截器開始,然後再到預設的5個攔截器。一般情況下我們想列印網路請求日誌,所以可以自定義Log攔截器,如果要給所有請求新增Header,同樣可以自定義Header攔截器。

    1. 失敗重試、重定向攔截器。
    2. 橋攔截器:主要是新增和刪除一些header
    3. 快取攔截器:根據快取策略,如果快取可用,直接返回快取資料。
    4. 連線池攔截器:連線池會快取http連結,連線池的好處是複用連線,少了3次握手,所以請求會更快
    5. .真正訪問網路的攔截器:內部使用okio去發請求

八.記憶體洩漏優化

關於記憶體洩漏的全部實戰解決方式

九.熟悉TCP/IP,http/https協議,熟悉使用者登入和授權以及使用者行為分析等方式

十.熟悉對稱/非對稱加密、hash、base64的實現方式以及相關應用

十一.Handler和AsyncTask機制

handler機制
方法一:使用sendMessage()

步驟: 步驟一:主執行緒匿名內部類建立Handler物件 步驟二:建立訊息物件 通過Message message=Message.obtain()建立一個message 步驟三:傳送訊息mHandler.sendMessage(msg);

原理:

UI執行緒建立一個Handler物件,然後在子執行緒中sendMessage傳送到在主執行緒的MessageQueue中,最後通過Lopper(訊息泵)物件去除MessageQueue中的訊息,分發回Handler的handleMessage()

AsyncTask機制
AsyncTask的原理 = 執行緒池 + Handler

執行緒池用於執行緒的排程、複用;handler用於非同步通訊

內部有一個SerialExecutor任務佇列執行緒池(任務排程)THREAD_POOL_EXECUTOR執行執行緒池(真正執行任務的執行緒池)內部handler(非同步通訊+訊息傳遞),

類、方法的介紹

AsynTask屬於抽象類需實現子類 execute(Params... params):觸發執行非同步執行緒任務,必需在UI執行緒中呼叫 onPreExecute():執行執行緒任務前的操作執行任務前呼叫,如顯示進度條等操作 doInBackground(Params params):接受輸入引數,執行任務中的耗時操作,返回執行結果。 onPostExecute(Resule result):接收執行緒任務執行結果,顯示到UI元件 onCancelled:將非同步任務設定為取消狀態,doInBackground()中判斷終止任務 點選檢視AsynTask原理具體說明

原理須知:

同步鎖修飾execute()從而保證AsyncTask中的任務是序列執行的

十二.MVC以及MVP

MVC的步驟:

首先使用者觸控View層(比如控制元件xml啥的都算view) Controller層(Activity,Fragment)做出反應去請求 Model層(http, 資料庫,sp)的資料,然後返回資料給C層,C層收到資料後通知View層進行更新

MVP的步驟:

首先使用者觸控View層(Activity,Fragment)如點選請求網路 然後view層呼叫Presenter(橋樑層)層去Model層(網路請求資料,資料庫資料,sp資料,contentProvider)拿對應的資料 最後P層通過初始化時持有的View層引用將view的更新通知給V層

十三.元件化、外掛化

元件化

元件化的優秀開源專案

外掛化

將app拆分成很多塊,每個模組都是一個apk,最終打包的時候講宿主apk和外掛apk分開打包,外掛apk通過動態下發到宿主apk。 用的是VirtualAPK

過程

1.宿主Module中的build.gradle中新增配置apply plugin 2.application中進行初始化 3.適當位置載入外掛

  PluginManager pluginManager = PluginManager.getInstance(base);
  File apk = new File(Environment.getExternalStorageDirectory(), "plugin.apk");
  if (apk.exists()) {
    try {
      pluginManager.loadPlugin(apk);
    } catch (Exception e) {
      e.printStackTrace();
      }
    } else {
      Toast.makeText(getApplicationContext(),"SDcard根目錄未檢測到plugin.apk外掛", Toast.LENGTH_SHORT).show();
  }
複製程式碼

4.載入外掛

public void click(View view){
    Intent intent = new Intent();
    intent.setClassName("com.emm.plugin","com.emm.plugin.Main2Activity");
    tartActivity(intent);
}

複製程式碼
原理:大致方案如下

原生apk就可作為外掛載入,外掛工程編譯生成apk後,即可通過宿主app載入,並在宿主中建立LoadedPlugin物件。再次啟動就會變得流暢 外掛apk需要在宿主Apk中提前佔坑,通過Hook Activity的啟動過程,“欺上瞞下”啟動外掛Apk中的Activity,其他三大元件都是通過代理的方式。

十四.TCP/IP協議簇,http/https協議,使用者登入授權、行為跟蹤

應用層 HTTP 、FTP 傳輸層 TCP、UDP 網路層 IP、ICMP、ARP 資料鏈路層 FDDI、IEEE 802.1A

使用者登入授權

Cookie是由伺服器端生成,伺服器需要客戶端儲存的內容,放在Set-Cookieheaders裡返回,客戶端會自動儲存 客戶端儲存的Cookie會在之後的所有請求裡攜帶進Cookieheader裡發回給伺服器 客戶端儲存Cookie是按照伺服器域名來分類的

行為跟蹤

簡單的說就是Cookies追蹤,利用第三方cookie來實現這一的機制 很多第三方作為跨域提供了使用者的token

十五.工廠、模板、觀察者、介面卡設計模式

工廠模式:寶馬和賓士類都實現car介面,用CarFactory返回例項化介面car,相當於一個工廠可以生產不同型別的例項 模板模式:抽象模板角色類,實現了父類所宣告的基本方法。子類實現需要強制實現的邏輯 觀察者模式: 1.抽象被觀察者介面,宣告新增通知刪除觀察者方法

public interface Observerable {
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();
}
複製程式碼

2.定義一個抽象觀察者介面

public interface Observer {
    public void update(String message);
}
複製程式碼

3.定義被觀察者,實現了Observerable介面,對介面方法進行了具體實現

public class WechatServer implements Observerable {
    //注意到這個List集合的泛型引數為Observer介面,設計原則:面向介面程式設計而不是面向實現程式設計
    private List<Observer> list;
    private String message;
    
    public WechatServer() {
        list = new ArrayList<Observer>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        
        list.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    //遍歷
    @Override
    public void notifyObserver() {
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }
    
    public void setInfomation(String s) {
        this.message = s;
        System.out.println("微信服務更新訊息: " + s);
        //訊息更新,通知所有觀察者
        notifyObserver();
    }

}
複製程式碼

4.定義具體觀察者,微信公眾號具體觀察者為使用者User

public class User implements Observer {
    private String name;
    private String message;
    
    public User(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        this.message = message;
        read();
    }
    
    public void read() {
        System.out.println(name + " 收到推送訊息: " + message);
    }
}
複製程式碼

5.編寫一個測試類,首先註冊了三個使用者,ZhangSan、LiSi、WangWu。公眾號釋出了一條訊息"PHP是世界上最好用的語言!",三個使用者都收到了訊息。 使用者ZhangSan看到訊息後頗為震驚,果斷取消訂閱,這時公眾號又推送了一條訊息,此時使用者ZhangSan已經收不到訊息,其他使用者

public class Test {
    public static void main(String[] args) {
        WechatServer server = new WechatServer();
        
        Observer userZhang = new User("ZhangSan");
        Observer userLi = new User("LiSi");
        Observer userWang = new User("WangWu");
        
        server.registerObserver(userZhang);
        server.registerObserver(userLi);
        server.registerObserver(userWang);
        server.setInfomation("PHP是世界上最好用的語言!");
        
        System.out.println("----------------------------------------------");
        server.removeObserver(userZhang);
        server.setInfomation("JAVA是世界上最好用的語言!");
    }
}
複製程式碼

介面卡模式:

十六.viewStub、ViewPager2、CoordinatorLayout

ViewStub:寬高都為 0 的不可見 View. 通過延遲載入佈局的方式優化佈局提升渲染效能,通過setVisibility或者直接呼叫inflate都會渲染布局檔案 ViewPager2:核心為RecyclerView+LinerLayoutManager,所以支援橫向和豎向的滾動,viewpager2可以承載fragment,需要繼承它提供的FragmentStateAdapter,還可以完整支援notifyDataSetChanged() CoordinatorLayout: 1.CoordinatorLayout繼承自viewgroup,但是使用類似於framLayout,只有CoordinatorLayout的直接子佈局才能響應。 2.是需要CoordinateLayout+AppBarLayout+CollapingToolbarLayout結合才有效果。


<android.support.design.widget.CoordinatorLayout
    android:id="@+id/main_content"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

    </android.support.design.widget.AppBarLayout>
 
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
 
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="15dp"
        android:src="@drawable/add_2"/>
 
</android.support.design.widget.CoordinatorLayout>
複製程式碼
  1. AppBarLayout設定屬性:layout_scrollFlags
    1. scroll|exitUntilCollapsed,子控制元件可以向上滾動出NestedScrollView父佈局時會摺疊到頂端
    2. scroll|enterAlways:只要向下滾動該佈局就會顯示出來,向上滾動該佈局就會收縮
    3. scroll|enterAlwaysCollapsed:向下滾動到最低端時,該佈局才會顯示出來

十七.jni使用

使用CMake進行ndk開發,它是一種比nake更高階的編譯配置工具,通過CMakeLists.txt,可以控制生成的Makefile,從而控制編譯過程、生成原始碼包、生成當前平臺安裝包。

使用流程
  1. 在java檔案中建立本地方法
  2. build專案後自動生成.h檔案
  3. 建立.cpp檔案,實現.h檔案中的方法
  4. 配置Cmake檔案,生成.so檔案

十八.螢幕適配

  1. 官方適配方案: 使用dp方式適配 使用資源目錄名加上-1920*1280等欄位 百分比佈局庫PercentRelativeLayoutPercentFrameLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#ff0000"
        app:layout_heightPercent="30%"
        app:layout_widthPercent="70%"
複製程式碼

ConstraintLayout layout_constraintHorizontal_chainStyle Guideline layout_constraintHorizontal_bias layout_constraintVertical_bias

  1. 開源適配方案: 今日頭條適配方案px=dp*density,動態修改裝置的density值,在不同解析度下達到相同的畫素密度

十九.Arouter、RxJava

Arouter
RxJava

二十.動畫、svg自定義控制元件

補間動畫: 主要通過xml中定義具有旋轉、縮放、平移、透明度的動畫

Animation animation = AnimationUtils.loadAnimation(MainActivity.this,R.anim.viewanimation);
                textView.startAnimation(animation);
複製程式碼

屬性動畫: 補間動畫只能定義兩個關鍵幀在透明(alpha)、旋轉(rorate)、位移(translate)和縮放(scale)這四個屬性的變換,但是屬性動畫可以定義任何屬性的變化。 補間動畫只能對 UI 元件執行動畫,但屬性動畫可以對任何物件執行動畫。

Animator: 提供建立屬性動畫的基類,基本不會直接使用這個類。 ValueAnimator:屬性動畫用到的主要的時間引擎,負責計算各個幀的屬性值。 ObjectAnimator: ValueAnimator 的子類,對指定物件的屬性執行動畫。 AnimatorSet:Animator 的子類,用於組合多個 Animator。

二十一.https HTTP over SSL

定義:給HTTP增加一個安全層,用於保障HTTP的加密傳輸,可以接受的對稱加密,非對稱加密,hash演算法 Https在與伺服器進行資料互動之前,會與伺服器進行一次通訊(握手)

1、瀏覽器將自身支援的加密演算法傳送給服務端

2、服務端篩選出一套加密演算法,以證照的形式發給瀏覽器

3、瀏覽器根驗證證照的合法性,據拿到的證照裡的公鑰加密一串訊息發給服務端

4、服務端使用私鑰解密資訊,驗證雜湊,並加密響應訊息給瀏覽器

5、瀏覽器解密響應訊息,並對訊息進行驗證,如果驗證通過,則可以進行加密資料互動

觸控事件的衝突解決

解決觸控事件衝突:

外部攔截。ViewGroup重寫onInterceptTouchEvent方法,預設不攔截,事件往下分發給子View,若返回true,則攔截此次事件,將事件傳給ViewGroup的onTouchEvent處理。

內部攔截。重寫子View的dispatchTouchEvent方法,方法中呼叫getParent().requestDisallowInterceptTouchEvent(true)方法,傳true則代表不希望ViewGroup攔截事件,傳false則代表希望ViewGroup攔截事件。

內部攔截。子View重寫onTouchEvent方法,返回true,則子View消費該次事件,返回false,該次事件返回給ViewGroup的onTouchEvent處理。

相關文章