Android 面試2018最新最全

爲啥分享的文章不會同步更新??? 觀看效果很差,請查看原文連接 blog.csdn.net/liu3364575/…java

相信你們都有面試的經歷,相對比面試官的問的一些問題其實都是基礎的知識,但就是一些基礎的知識咱們也不是很完美的回答出來,咱們也知道如今的開發人員不少,一家公司一個崗位就會有不少的開發者投遞,在那麼多開發者中你如何讓面試官很深的認識你,給面試官一個很深的印象,能讓他在技術水平差很少的狀況的下第一個想起的是你。 從這篇文章對整個面試中所問到的問題進行梳理,查缺補漏。android

JAVA String,StringBuffer,StringBuilder區別? 通常回答是這樣的: String 字符串常量 StringBuffer 字符串變量(線程安全) StringBuilder 字符串變量(非線程安全) 面試的時候千萬不要這麼說,這樣說會讓面試官你還只停留在會用的層面,不知道原理,你應該這麼說:nginx

String,StringBuffer,StringBuilder最終底層存儲與操做的都是char數組,可是String裏面的char數組是final的,而StringBuffer,StringBuilder不是,也就是說,String是不可變的,想要新的字符串只能從新生成String;而StringBuffer和StringBuilder只須要修改底層的char數組就行,相對來講,開銷要小不少,String的大多數方法都是從新new一個新String對象返回,頻繁從新生成容易生成不少垃圾。web

爲何StringBuffer 是線程安全的? StringBuffer是線程安全的,StringBuilder是線程不安全的,由於StringBuffer的方法是加了synchronized鎖起來了的,而StringBuilder沒有面試

增刪比較多時用StringBuffer或StringBuilder(注意單線程與多線程)。算法

HashMap的實現機制? HashMap其實是一個「鏈表散列」的數據結構,即數組和鏈表的結合體。HashMap底層就是一個數組結構,數組中的每一項又是一個鏈表。當新建一個HashMap的時候,就會初始化一個數組。shell

/**數據庫

  • The table, resized as necessary. Length MUST Always be a power of two. */ transient Entry[] table;

static class Entry<K,V> implements Map.Entry<K,V> { final K key; V value; Entry<K,V> next; final int hash; …… } 1 2 3 4 5 6 7 8 9 10 11 12 能夠看出,Entry就是數組中的元素,每一個 Map.Entry 其實就是一個key-value對,它持有一個指向下一個元素的引用,這就構成了鏈表。canvas

HashMap若是Hash衝突了怎麼解決? 能夠看下這篇文章 https://blog.csdn.net/qq_27093465/article/details/52269862後端

如何線程安全的使用HashMap? 無非就三種實現方式: 1)Hashtable 2)ConcurrentHashMap 3)Synchronized Map

//Hashtable Map<String, String> hashtable = new Hashtable<>();

//synchronizedMap Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>());

//ConcurrentHashMap Map<String, String> concurrentHashMap = new ConcurrentHashMap<>(); 1 2 3 4 5 6 7 8 HashTable源碼中是使用synchronized來保證線程安全的

public synchronized V get(Object key) { // 省略實現 } public synchronized V put(K key, V value) { // 省略實現 } 1 2 3 4 5 6 因此當一個線程訪問HashTable的同步方法時,其餘線程若是也要訪問同步方法,會被阻塞住。舉個例子,當一個線程使用put方法時,另外一個線程不但不能夠使用put方法,連get方法都不能夠,好霸道啊!!!so~~,效率很低,如今基本不會選擇它了。

ConcurrentHashMap(如下簡稱CHM)是JUC包中的一個類,Spring的源碼中有不少使用CHM的地方。CHM的一些重要特性和什麼狀況下應該使用CHM。須要注意的是,上面博客是基於Java 7的,和8有區別,在8中CHM摒棄了Segment(鎖段)的概念,而是啓用了一種全新的方式實現,利用CAS算法。

// synchronizedMap方法 public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) { return new SynchronizedMap<>(m); } // SynchronizedMap類 private static class SynchronizedMap<K,V> implements Map<K,V>, Serializable { private static final long serialVersionUID = 1978198479659022715L;

private final Map<K,V> m;     // Backing Map
   final Object      mutex;        // Object on which to synchronize

   SynchronizedMap(Map<K,V> m) {
       this.m = Objects.requireNonNull(m);
       mutex = this;
   }

   SynchronizedMap(Map<K,V> m, Object mutex) {
       this.m = m;
       this.mutex = mutex;
   }

   public int size() {
       synchronized (mutex) {return m.size();}
   }
   public boolean isEmpty() {
       synchronized (mutex) {return m.isEmpty();}
   }
   public boolean containsKey(Object key) {
       synchronized (mutex) {return m.containsKey(key);}
   }
   public boolean containsValue(Object value) {
       synchronized (mutex) {return m.containsValue(value);}
   }
   public V get(Object key) {
       synchronized (mutex) {return m.get(key);}
   }

   public V put(K key, V value) {
       synchronized (mutex) {return m.put(key, value);}
   }
   public V remove(Object key) {
       synchronized (mutex) {return m.remove(key);}
   }
   // 省略其餘方法
複製代碼

} 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 synchronizedMap從源碼中能夠看出調用synchronizedMap()方法後會返回一個SynchronizedMap類的對象,而在SynchronizedMap類中使用了synchronized同步關鍵字來保證對Map的操做是線程安全的。

HasMap爲何會線程不安全? 我的以爲HashMap在併發時可能出現的問題主要是兩方面, 首先若是多個線程同時使用put方法添加元素,並且假設正好存在兩個put的key發生了碰撞(hash值同樣),那麼根據HashMap的實現,這兩個key會添加到數組的同一個位置,這樣最終就會發生其中一個線程的put的數據被覆蓋。

第二就是若是多個線程同時檢測到元素個數超過數組大小*loadFactor,這樣就會發生多個線程同時對Node數組進行擴容,都在從新計算元素位置以及複製數據,可是最終只有一個線程擴容後的數組會賦給table,也就是說其餘線程的都會丟失,而且各自線程put的數據也丟失。

HashMap出現死循環的緣由? 由於多線程會致使HashMap的Entry節點造成環鏈,這樣當遍歷集合時Entry的next節點用於不爲空,從而造成死循環

Activity: 當面試官問你什麼Activity,你是否是會以爲一陣懵* ?

在平常應用中,Android是用戶交互的接口,他提供了一個界面,讓用戶進行點擊,各類滑動操做等。

Activity的四種狀態: running / paused / stopped / killed running:點擊屏幕,屏幕作出響應,處於activity棧頂的狀態 paused:失去焦點不能進行操做,或者是一個透明的在棧頂的Activity,注意並非被銷燬了啊,它的成員信息和變量都還在,固然還有另一種狀態,當內存緊張的時候會北迴收掉 stopped:當一個Activity被另一個Activity徹底覆蓋的時候,被覆蓋的那個處於stopped狀態,不可見,成員信息和變量都還在,若是內存緊張也是會被回收的 killed:已經被系統回收

生命週期: 啓動:onCreate >> onStart >> onResume 點擊HOME鍵回到主界面:onPause >> onStop 再次回到遠Activity:onResrart>>onStart >> onResume 退出當前Activity:onPause >> onStop >> onDestroy

進程優先級: 前臺 / 可見 /服務 /後臺 / 空 前臺:正在進行交互的Activity或者與前臺activity綁定的services 可見:一個activity可見但並處於前臺,不能點擊 服務:在後臺開啓的服務 後臺:當一個Activity被點擊home鍵,退居後臺,沒有=被回收 空 :不屬於前面四種進程的任意一種,處於緩存的目的而保留

啓動模式: standard / singletop / singletask / singleinstance

如何配置Activity的啓動模式? 直接在AndroidManifest.xml配置的android:launchMode屬性爲以上四種之一便可

standrd:標準模式,每次啓動都會從新建立一個activity實例加入到任務棧中,不會考慮是否是有此實例存在,不會複用,消耗內存資源

singletop :棧頂複用模式,只檢測任務棧棧頂,只有在棧頂的Activity不會被建立,就算是在第二位也是會被建立

singletask:棧內複用模式,也是一個單例模式,檢測整個任務棧,若是有並把在之上的實例所有移除掉,回掉onNewIntent方法

singleinstance:一個activity若是在整個系統中只存在一個實例,並且這個activity獨享整個任務棧

應用場景: singleTop:適合接收通知啓動的內容顯示頁面。例如,某個新聞客戶端的新聞內容頁面,若是收到10個新聞推送,每次都打開一個新聞內容頁面是很煩人,另外,singleTop啓動模式適合於一些不經常使用的Activity頁面,好比「找回密碼」、「設置界面」等。

singleTask:最典型的樣例就是應用中展現的主頁(Home頁),假設用戶在主頁跳轉到其餘頁面,運行屢次操做後想返回到主頁,假設不使用SingleTask模式,在點擊返回的過程當中會屢次看到主頁,這明顯就是設計不合理了。

singleInstance:好比說,使用微信調起本身的客戶端某個頁面,不作任何處理的狀況下,按下回退或者當前Activity.finish(),頁面不會停留在本身的客戶端而是返回到微信的客戶端頁面。可是若是這個頁面的啓動模式設置爲singleTask,當按下返回鍵或者Activity。finish(),頁面都會停留在本身的客戶端(由於本身的Application回退棧不爲空),這明顯不符合邏輯的。產品的要求是,回退必須回到微信客戶端,並且要保證不殺死本身的Application.所以,顯然其餘的其餘的啓動模式都不具有這個功能。

使用方法: 方法一:

android:launchMode="standard|singleInstance|single Task|singleTop 1 使用android:launchMode=」standard|singleInstance|single Task|singleTop」來控制Acivity任務棧。

方法二:

Intent Flags: Intent intent=new Intent(); intent.setClass(MainActivity.this, MainActivity2.class); intent.addFlags(Intent. FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); 1 2 3 4 5 Flags有不少,好比: Intent.FLAG_ACTIVITY_NEW_TASK 至關於singleTask Intent. FLAG_ACTIVITY_CLEAR_TOP 至關於singleTop

scheme(sigeimo)跳轉協議: android中的scheme是一種頁內跳轉協議,是一種很是好的實現機制,經過定義本身的scheme協議,能夠很是方便的在app內部跳轉到各個界面;經過scheme協議,服務器能夠定製化告訴app跳轉到哪一個頁面,能夠經過通知欄消息欄定製化跳轉頁面,也能夠經過H5頁面中定義鏈接跳轉指定的activity頁面等

應用場景: 1 服務端下發一個url路徑,客戶端根據下方的路徑跳轉到指定界面 2 從H5跳轉到App內 3 App根據url挑戰到另外的一個App

兩個 Activity 之間跳轉時必然會執行的是哪幾個方法? 通常狀況下好比說有兩個 activity,分別叫 A,B,當在 A 裏面激活 B 組件的時候, A 會調用 onPause()方法,而後 B 調用 onCreate() ,onStart(), onResume()。 這個時候 B 覆蓋了窗體, A 會調用 onStop()方法. 若是 B 是個透明的,或者 是對話框的樣式, 就不會調用 A 的 onStop()方法。

橫豎屏切換時 Activity 的生命週期? 此時的生命週期跟清單文件裏的配置有關係。 1.不設置 Activity 的 android:configChanges 時,切屏會從新調用各個生命週期默認首先銷燬當前 activity,而後從新加載。 2.設置 Activity android:configChanges=」orientation|keyboardHidden|screenSize」時,切 屏不會從新調用各個生命週期,只會執行 onConfigurationChanged 方法。 一般在遊戲開發, 屏幕的朝向都是寫死的。

如何將一個 Activity 設置成窗口的樣式? 只須要給咱們的 Activity 配置以下屬性便可。 android:theme=」@android:style/Theme.Dialog」

Android 中的 Context, Activity,Appliction 有什麼區別? 相同:Activity 和 Application 都是 Context 的子類。 Context 從字面上理解就是上下文的意思,在實際應用中它也確實是起到了管理 上下文環境中各個參數和變量的總用,方便咱們能夠簡單的訪問到各類資源。

不一樣:維護的生命週期不一樣。Context 維護的是當前的 Activity 的生命週期, Application 維護的是整個項目的生命週期。使用 context 的時候,當心內存泄露,防止內存泄露,注意一下幾個方面: 1)不要讓生命週期長的對象引用 activity context,即保證引用 activity 的對 象要與 activity 自己生命週期是同樣的。 2 )對於生命週期長的對象,能夠使用 application,context。 3 )避免非靜態的內部類,儘可能使用靜態類,避免生命週期問題,注意內部類 對外部對象引用致使的生命週期變化。

如何獲取當前屏幕Activity的對象? 使用ActivityLifecycleCallbacks 應用場景:能夠利用ActivityLifecycleCallbacks 作一些數據埋點,統計之類的應用,對其統一作處理。這樣對減小Activity的代碼入侵。儘可能簡化和模塊化的注入生命週期方法。

ActivityLifecycleCallbacks 是什麼? 見名知意,Activity生命週期回調,Application經過此接口提供了一套回調方法,用於讓開發者對Activity的生命週期事件進行集中處理。 可是這個要求API 14+ (Android 4.0+)以上使用,幸虧咱們這個最低支持,知足需求。

ActivityLifecycleCallbacks 怎麼使用? 重寫Application的onCreate()方法,或在Application的無參構造方法內,調用Application.registerActivityLifecycleCallbacks()方法,並實現ActivityLifecycleCallbacks接口

知道onNewIntent嗎? 若是IntentActivity處於任務棧的頂端,也就是說以前打開過的Activity,如今處於onPause、onStop 狀態的話,其餘應用再發送Intent的話,執行順序爲: onNewIntent,onRestart,onStart,onResume。

除了用Intent 去啓動一個Activity,還有其餘方法嗎? 使用adb shell am 命令

1)ams啓動一個activity adb shell am start com.example.fuchenxuan/.MainActivity 2)am發送一個廣播,使用action adb shell am broadcast -a magcomm.action.TOUCH_LETTER

Android Service與Activity之間通訊的幾種方式? 經過Binder對象 1)當Activity經過調用bindService(Intent service, ServiceConnection conn,int flags),獲得一個Service的一個對象,經過這個對象咱們能夠直接訪問Service中的方法。 2)經過Broadcast Receiver(廣播)的形式 3)EventBus 是一個Android開源事件總線框架 後面咱們會有專門的講解。

TaskAffinity 是什麼? 標識Activity任務棧名稱的屬性:TaskAffinity,默認爲應用包名

若是新Activity是透明主題時,舊Activity會不會走onStop? 不會!

android徹底退出應用程序的三種方式?

第一種方法:首先獲取當前進程的id,而後殺死該進程。 建議使用這種方式

android.os.Process.killProcess(android.os.Process.myPid()) 1 第二種方法:終止當前正在運行的Java虛擬機,致使程序終止

System.exit(0); 1 2 第三種方法:強制關閉與該包有關聯的一切執行

ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
manager.restartPackage(getPackageName()); 1 2 使用這種方式關閉應用程序須要加上權限

1 介紹下Android應用程序啓動過程 1)Launcher經過Binder進程間通訊機制通知ActivityManagerService,它要啓動一個Activity;

2)ActivityManagerService經過Binder進程間通訊機制通知Launcher進入Paused狀態;

3)Launcher經過Binder進程間通訊機制通知ActivityManagerService,它已經準備就緒進入Paused狀態,因而ActivityManagerService就建立一個新的進程,用來啓動一個ActivityThread實例,即將要啓動的Activity就是在這個ActivityThread實例中運行;

4)ActivityThread經過Binder進程間通訊機制將一個ApplicationThread類型的Binder對象傳遞給ActivityManagerService,以便之後ActivityManagerService可以經過這個Binder對象和它進行通訊;

5)ActivityManagerService經過Binder進程間通訊機制通知ActivityThread,如今一切準備就緒,它能夠真正執行Activity的啓動操做了。 若是想深刻研究的能夠查看羅昇陽大神的博客https://blog.csdn.net/luoshengyang/article/details/6689748

Fragment: 三個小問題看你能完美解答幾個 1 Fragment爲何被稱爲第五大組件? 2 Fragment的生命週期 ? 3 Fragment之間的通訊 ?

1 Fragment爲何被稱爲第五大組件? 首先Fragment的使用頻率並不低於其餘四大組件,他有本身的生命週期,同時能夠動態靈活的加載到Activity中,因此說Fragment能夠被稱爲第五大組件

加載到Activity的兩種方式: 1)添加Fragment到Activity的佈局文件當中,也叫靜態加載,name屬性哦 2)動態的在activity中添加fragment ,也叫動態加載 步驟: FragmentManage用來管理全部要啓動的fragment,並用FragmentTransaction添加和替換相對應的fragment,並用容器資源來做爲標誌位來設置fragment所要顯示到activity當中的位置,最後提交commit方法 (1)建立待添加的碎片實例 (2)獲取FragmentManager,在活動中能夠直接經過調用 getSupportFragmentManager()方法獲得。 (3)開啓一個事務,經過調用beginTransaction()方法開啓。 (4)向容器內添加或替換碎片,通常使用repalce()方法實現,須要傳入容器的id和待添加的碎片實例。 (5)提交事務,調用commit()方法來完成。

FragmentPageAdapter與FragmentStatePageAdapter的區別? 1 FragmentStatePageAdapter適合界面多,FragmentPageAdapter適合界面少 2 FragmentStatePageAdapter比FragmentPageAdapter更節省內存 源碼分析: FragmentPageAdapter適用於頁面較少的狀況下,由於只對ui分離並無回收內存, 由於源碼裏面destoryItem是detach方法()只是對fragment和activity的ui脫離開來,並不回收內存 FragmentStatePageAdapter用於界面較多的狀況下,界面多也就意味着更加的消耗內存,FragmentStatePageAdapter在每次切換fragment的時候,他是回收內存的,由於源碼裏面destoryItem的remove方法真正的釋放的內存

Fragement的生命週期: onAttach >> onCreate >> onCreateView >> onActivityCreated >>onStart >> onResume >> onPause >> onStop >> onDestoryView >> onDestory >>onDetach 很顯然你要是像背書似的將上面的生命週期說一遍,你認爲你跟其餘的競爭者有什麼優點?

你應該將Activity與Fragment的生命週期結合起來講: 首先,調用Activity的onCreate方法 當Fragment建立的時候會執行onAttach,是在Activity與fragment關聯以後調用的 在以後執行onCreate方法,也就是在fragment建立的時候調用,注意,此時的activity尚未建立完畢 在調用fragment的onCreateView方法,系統首次繪製用戶界面的時候調用 調用fragment的onActivityCreated方法,也就是activity被渲染繪製成功後調用, 如今是要調用activity的onStart的方法,當activity可見以後調用, fragment的onStart方法,表示fragment也可見了 接着調用activity的onResume的方法,表示當前activity能夠與用戶交互了,當activity可見以後調用 fragment的onResume方法,表示當前fragment也能夠與用戶進行交互操做了,以上步驟完成了從建立到交互的全部步驟

在以後,Fragment的onPause Activity的onPause Fragment的onStop Activity的onStop 如今來到了Frament的onDestoryView方法,表示當前fragment不在被使用,界面銷燬,緊接着來到onDestory方法,表示fragment已經銷燬了,最後調用onDetach來解除與activity的聯繫 最後調用Activity的onDestory方法

Fragment通訊: 1)在Fragment中調用Activity的方法 geyActivity 2)在Activity中調用Fragment的方法 接口回調(在Fragment建立接口,在Activity實現) 3)在Fragment調用Fragment的方法 getActivity.findFragmentById 或者廣播

Fragment的replace、add、remove?

add:將一個fragment實例添加到Activity的最上層,通常在使用add的時候會配合 hide,show一塊兒使用,爲了不Fragment的重複建立節省資源。 remove:將fragment從fragment隊列中刪除 replace:替換fragment的實例,replace是FragmentManager的方法

commitAllowingStateLoss與commit的區別? Activity被系統回收(界面已經不存在了),爲了能在下次打開的時候恢復原來的樣子,系統爲咱們保存界面的全部狀態,這個時候再去修改界面理論上確定是不被容許的,爲了不這種異常能夠使用:

transaction.commitAllowingStateLoss(); 1 來提交添加Fragment到Activity的事務,與commit()不一樣的是使用這種方法容許丟失界面的狀態和信息。

ViewPager與Fragment結合使用時的懶加載問題? 所謂的 「懶加載」 就是數據只有在Fragment對於用戶可見的時才進行加載,咱們須要斷定Fragment在何時是處於可見的狀態。通常咱們一般是經過Fragment中的生命週期方法onResume來判斷Fragment是否可見,可是因爲ViewPager預加載的特性,Fragment即使不可見也會執行onResume方法,能夠經過setUserVisibleHint()方法來進行判斷:

何時被調用?

當fragment被建立的時,setUserVisibleHint(boolean isVisibleToUser)方法會被調用,且傳入參數值爲false。

當fragment可見時,setUserVisibleHint(boolean isVisibleToUser)方法會被調用,且傳入參數值爲true。

當fragment由 可見 -> 不可見 時,setUserVisibleHint(boolean isVisibleToUser)方法會被調用,且傳入參數值爲false。 1 2 3 4 5 因此咱們只須要當setUserVisibleHint(boolean isVisibleToUser)方法中的 isVisibleToUser 參數的值爲true的時候咱們纔開始進行數據的加載就能夠了。

可是有一點須要須要注意的是 setUserVisibleHint(boolean isVisibleToUser)方法在Fragment的生命週期方法onCreate 以前調用的,也就是說他並不在Fragment的生命週期中。既然是在 onCreate 方法以前被調用,這樣就存在許多不肯定因素,若是Fragmnet的View尚未完成初始化以前,就在setUserVisibleHint()方法中進行UI的操做,這樣顯然會致使空指針的出現。所以咱們須要對Fragment建立的View進行緩存,確保緩存的View不爲空的狀況下咱們才能夠在setUserVisibleHint方法中進行UI操做。

Service Service是什麼? 四大組件之一,能夠在後臺處理一些耗時的邏輯,也能夠執行某些長時間運行的任務,並且看不到界面,包括在程序退出的時候依然能在繼續運行

Service與Broadcastrecevier有一個共同點,都是運行在主線程當中,都不能進行長耗時操做

Service與Thread的區別? Thread程序最小的執行單元,Thread能夠進行異步操做,相對獨立;而Service是Android的一種機制,若是是本地的Service,依賴與它所在的主線程之上,相比Thread沒有那麼獨立

爲何要用Service而不是Thread呢? Thread的運行是獨立於Activity的,也就是當一個Activity被finish以後,若是沒有主動中止Thread或者Thread中的run沒有執行完畢時那麼這個線程會一直執行下去。所以這裏會出現一個問題:當 Activity 被 finish 以後,你再也不持有該 Thread 的引用。另外一方面,你沒有辦法在不一樣的 Activity 中對同一 Thread 進行控制。

Service 是否在 main thread 中執行, service 裏面是否 能執行耗時的操做? 默認狀況,若是沒有顯示的指 servic 所運行的進程, Service 和 activity 是運 行在當前 app 所在進程的 main thread(UI 主線程)裏面。 service 裏面不能執行耗時的操做(網絡請求,拷貝數據庫,大文件 ) 特殊狀況 ,能夠在清單文件配置 service 執行所在的進程 ,讓 service 在另 外的進程中執行

1 2 3 Service 裏面能夠彈吐司麼? 能夠的。彈吐司有個條件就是得有一個 Context 上下文,而 Service 自己就是 Context 的子類,所以在 Service 裏面彈吐司是徹底能夠的。好比咱們在 Service 中完成下載任務後能夠彈一個吐司通知用戶

Service 的 onStartCommand 方法有幾種返回值?各表明什麼意思?

有四種返回值,不一樣值表明的意思以下: START_STICKY:若是 service 進程被 kill 掉,保留 service 的狀態爲開始狀態,但不保留遞送的 intent 對象。隨 後系統會嘗試從新建立 service,因爲服務狀態爲開始狀態,因此建立服務後必定會調用 onStartCommand(Intent,int,int)方法。若是在此期間沒有任何啓動命令被傳遞到 service,那麼參數 Intent 將爲 null。

START_NOT_STICKY:「非粘性的」。使用這個返回值時,若是在執行完 onStartCommand 後,服務被異常 kill 掉,系統不會自動重啓該服務。

START_REDELIVER_INTENT:重傳 Intent。使用這個返回值時,若是在執行完 onStartCommand 後,服務被異 常 kill 掉,系統會自動重啓該服務,並將 Intent 的值傳入。

START_STICKY_COMPATIBILITY:START_STICKY 的兼容版本,但不保證服務被 kill 後必定能重啓。

Service 的 onRebind(Intent)方法在什麼狀況下會執行? 若是在 onUnbind()方法返回 true 的狀況下會執行,不然不執行。

Activity 調用 Service 中的方法都有哪些方式? Binder: 經過 Binder 接口的形式實現,當 Activity 綁定 Service 成功的時候 Activity 會在 ServiceConnection 的類 的 onServiceConnected()回調方法中獲取到 Service 的 onBind()方法 return 過來的 Binder 的子類,而後經過對象調用方法。 Aidl: aidl 比較適合當客戶端和服務端不在同一個應用下的場景。

Messenger: 它引用了一個Handler對象,以便others可以向它發送消息(使用mMessenger.send(Message msg)方法)。該類容許跨進程間基於Message的通訊(即兩個進程間能夠經過Message進行通訊),在服務端使用Handler建立一個Messenger,客戶端持有這個Messenger就能夠與服務端通訊了。一個Messeger不能同時雙向發送,兩個就就能雙向發送了

如何提升service的優先級? 能夠用 setForeground(true) 來設置 Service 的優先級。

service 如何定時執行? 使用AlarmManager,根據AlarmManager的工做原理,alarmmanager會定時的發出一條廣播,而後在本身的項目裏面註冊這個廣播,重寫onReceive方法,在這個方法裏面啓動一個service,而後在service裏面進行網絡的訪問操做,當獲取到新消息的時候進行推送,同時再設置一個alarmmanager進行下一次的輪詢,當本次輪詢結束的時候能夠stopself結束改service。這樣即便這一次的輪詢失敗了,也不會影響到下一次的輪詢。這樣就能保證推送任務不會中斷

在 service 的生命週期方法 onstartConmand()可不能夠執行網絡操做?如何在 service 中執行網絡操做? 能夠直接在 Service 中執行網絡操做,在 onStartCommand()方法中能夠執行網絡操做

Service 和 Activity 在同一個線程嗎? 對於同一 app 來講默認狀況下是在同一個線程中的,main Thread (UI Thread)。

什麼是 IntentService?有何優勢? 會建立獨立的工做線程來處理全部的 Intent 請求; 會建立獨立的工做線程來處理 onHandleIntent()方法實現的代碼,無需 處理多線程問題; 全部請求處理完成後,IntentService 會自動中止,無需調用 stopSelf()方法 中止 Service; 爲 Service 的 onBind()提供默認實現,返回 null; 爲 Service 的 onStartCommand 提供默認實現,將請求 Intent 添加到隊列 中;

Activity 怎麼和 Service 綁定,怎麼在 Activity 中啓動自 己對應的 Service? Activity 經過 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 進行綁定,當綁定成功的時候 Service 會將代理對象經過回調 的形式傳給 conn,這樣咱們就拿到了 Service 提供的服務代理對象。 在 Activity 中能夠經過 startService 和 bindService 方法啓動 Service。一 般狀況下若是想獲取 Service 的服務對象那麼確定須要經過 bindService()方 法,好比音樂播放器,第三方支付等。若是僅僅只是爲了開啓一個後臺任務那麼 能夠使用 startService()方法。

IntentService 適用場景 IntentService 內置的是 HandlerThread 做爲異步線程,每個交給 IntentService 的任務都將以隊列的方式逐個被執行到,一旦隊列中有某個任務執行時間過長,那麼就會致使後續的任務都會被延遲處理 正在運行的 IntentService 的程序相比起純粹的後臺程序更不容易被系統殺死,該程序的優先級是介於前臺程序與純後臺程序之間的

Broadcast Receiver 廣播的定義: 在Android中,Broadcast是一種普遍運用在程序之間的傳輸信息的機制,Android中咱們要發送的廣播內容中是一個Intent,這個Intent能夠攜帶咱們要傳輸的數據

廣播的使用場景: 1)在同一個App具備多個進程的不一樣組件之間的消息傳遞 2)不一樣app之間的消息通訊

廣播的種類: 1)普通廣播 2)系統廣播 (sendOrderedBroadcast) 3 ) 本地廣播(只在app內部傳播)

不一樣註冊方式廣播接收器回調onReceive(context, intent)中context類型不一致? manifest靜態註冊的ContextReceiver,回調onReceive(context, intent)中的context是ReceiverRestrictedContext;

代碼動態註冊的ContextReceiver,回調onReceive(context, intent)中的context是Activity Context;

內部實現機制? 1)自定義廣播接受者Broadcast Receiver,並複寫onRecvice方法 2)經過Binder機制像AMS進行註冊 3)廣播發送者經過Binder機制像AMS發送廣播 4)AMS查找符合相應條件(IntentFilter/Permission等)的Broadcast Receiver,將廣播發送到Broadcast Receiver相應的消息隊列循環當中去(通常是Activity中) 5)消息循環拿到此廣播,回調Broadcast Receiver中的onReceive方法、

如何讓本身的廣播只讓指定的 app 接收? 經過自定義廣播權限來保護本身發出的廣播。 在清單文件裏receiver必須有這個權限才能收到廣播。 首先,須要定義權限: 而後,聲明權限: 這時接收者就能收到發送的廣播。

廣播的優先級對無序廣播生效嗎? 生效的**

動態註冊的廣播優先級誰高? 誰先註冊誰優先級高。

如何判斷當前 BroadcastReceiver 接收到的是有序廣播仍是無序廣播? 在 BroadcastReceiver 類中 onReceive()方法中,能夠調用 boolean b = isOrderedBroadcast();判斷接收到的廣播是否爲有序廣播。

粘性廣播有什麼做用?怎麼使用?

粘性廣播主要爲了解決,在發送完廣播以後,動態註冊的接收者,也可以收到廣播。舉個例子首先發送一廣播,個人接收者是經過程序中的某個按鈕動態註冊的。若是不是粘性廣播,我註冊完接收者確定沒法收到廣播了。這是經過發送粘性廣播就可以在我動態註冊接收者後也能收到廣播。

網絡 HttpConnection 與HttpURLConnection的區別? 在Android 2.2版本以前,HttpClient擁有較少的bug,所以使用它是最好的選擇 2.3以後使用HttpURLConnection,它的API簡單,體積較小,壓縮和緩存機制能夠有效地減小網絡訪問的流量,在提高速度和省電方面也起到了較大的做用,利於維護與優化

TCP與UDP的區別? 1)基於鏈接與無鏈接 2)對系統資源的要求(TCP較多,UDP較少) 3)UDP程序結構較簡單一些 4)流模式與數據包模式 5)TCP保證數據的順序性以及正確性,UDP不能保證,可能存在丟包

Socket: soket是套接字,咱們能夠先在服務端初始化ServerSocket,而後對指定的端口進行綁定與監聽,經過調用accept方法與getInputstream方法進行等待客戶端的鏈接與數據的接收。如今客戶端進行建立socket對象傳入ip和端口號,經過getOutputStream進行數據的輸入,而且制定結束字符,不然服務端會一直處於阻塞狀態。

socket.close() 與socket.shutdownOutput()的區別? 1)在客戶端或者服務端經過socket.shutdownOutput()都是單向關閉的,即關閉客戶端的輸出流並不會關閉服務端的輸出流,因此是一種單方向的關閉流; 2)經過socket.shutdownOutput()關閉輸出流,但socket仍然是鏈接狀態,鏈接並未關閉 3)若是直接關閉輸入或者輸出流,即:in.close()或者out.close(),會直接關閉socket

socket長鏈接? 在不關閉流的狀況下,開啓循環線程進行定時發送與服務端約定的心跳包數據

Handler 什麼是Handler? handler經過發送和處理Message和Runnable對象來關聯相對應線程的MessageQueue 做用: 1)可讓對應的Message和Runnable在將來的某個時間點進行相應處理 2)讓本身想要處理的耗時操做放在子線程,讓更新ui的操做放在主線程

Handler發送消息的幾種方式? 1)post(Runnable)延遲消息處理 2)sendMessage(message)

PS:post(Runnable)的Runnable中能夠更新UI嗎? 能夠的 ,由於常常會post一個Runnable,處理的代碼直接寫在Runnable的run方法中,其實就是將這個Runnable發送到Handler所在線程(通常是主線程)的消息隊列中。sendMessage方法主線程處理方法通常則是寫在handleMessage中

Handler處理消息有哪幾種方式?

直接看dispatchMessage()源碼

//1. post()方法的最終處理方法 private static void handleCallback(Message message) { message.callback.run(); } //2. sendMessage()方法的最終處理方法 public void handleMessage(Message msg) { } 1 2 3 4 5 6 7 8 Handler、Message、Looper、MessageQueue

Message(消息) 定義:Handler接收和處理的消息對象(Bean對象) 做用:通訊時相關信息的存放和傳遞

ThreadLocal 定義:ThreadLocal是線程內部的存儲類,經過它能夠實如今每一個線程中存儲本身的私有數據。即數據存儲之後,只能在指定的線程中獲取這個存儲的對象,而其它線程則不能獲取到當前線程存儲的這個對象。 做用:負責存儲和獲取本線程的Looper

MessageQueue(消息隊列) 定義:採用單鏈表的數據結構來存儲消息列表 做用:用來存放經過Handler發過來的Message,按照先進先出執行

Handler(處理者) 定義:Message的主要處理者 做用:負責發送Message到消息隊列&處理Looper分派過來的Message

Looper(循環器) 定義:扮演Message Queue和Handler之間橋樑的角色 做用: 消息循環:循環取出Message Queue的Message 消息派發:將取出的Message交付給相應的Handler

首先知道定義人,而後結合關係說清楚一些在加上HandlerThread基本上Handler這塊是沒什麼大問題了

Message、Handler、MessageQueue、Looper的之間的關係? 首先,是這個MessagQueue,MessageQueue是一個消息隊列,它能夠存儲Handler發送過來的消息,其內部提供了進隊和出隊的方法來管理這個消息隊列,其出隊和進隊的原理是採用單鏈表的數據結構進行插入和刪除的,即enqueueMessage()方法和next()方法。這裏提到的Message,其實就是一個Bean對象,裏面的屬性用來記錄Message的各類信息。 而後,是這個Looper,Looper是一個循環器,它能夠循環的取出MessageQueue中的Message,其內部提供了Looper的初始化和循環出去Message的方法,即prepare()方法和loop()方法。在prepare()方法中,Looper會關聯一個MessageQueue,並且將Looper存進一個ThreadLocal中,在loop()方法中,經過ThreadLocal取出Looper,使用MessageQueue的next()方法取出Message後,判斷Message是否爲空,若是是則Looper阻塞,若是不是,則經過dispatchMessage()方法分發該Message到Handler中,而Handler執行handlerMessage()方法,因爲handlerMessage()方法是個空方法,這也是爲何須要在Handler中重寫handlerMessage()方法的緣由。這裏要注意的是Looper只能在一個線程中只能存在一個。這裏提到的ThreadLocal,其實就是一個對象,用來在不一樣線程中存放對應線程的Looper。 最後,是這個Handler,Handler是Looper和MessageQueue的橋樑,Handler內部提供了發送Message的一系列方法,最終會經過MessageQueue的enqueueMessage()方法將Message存進MessageQueue中。咱們平時能夠直接在主線程中使用Handler,那是由於在應用程序啓動時,在入口的main方法中已經默認爲咱們建立好了Looper。

Handler引發的內存泄漏以及解決辦法?

HandlerThread做用 當系統有多個耗時任務須要執行時,每一個任務都會開啓一個新線程去執行耗時任務,這樣會致使系統屢次建立和銷燬線程,從而影響性能。爲了解決這一問題,Google提供了HandlerThread,HandlerThread是在線程中建立一個Looper循環器,讓Looper輪詢消息隊列,當有耗時任務進入隊列時,則不須要開啓新線程,在原有的線程中執行耗時任務便可,不然線程阻塞。

HandlerThread是什麼?有哪些特色

1)HandlerThread本質上是一個線程類,它繼承了Thread 2)HandlerThread有本身內部Looper對象,能夠進行Looper循環 3)經過獲取HandlerThread的looper對象傳遞給Handler對象,能夠在handlerMessage方法中執行異步任務 4)優勢是不會阻塞,減小對性能的消耗,缺點是不能同時進行多任務的處理,須要等待進行處理 5)與線程池注重併發不一樣,HandlerThread是一個串行隊列,HandlerThread背後只有一個線程

子線程爲何不能開啓handler? handler在調用sendMessage或者post(Runnable)的時候都須要一個MessageQueue 消息隊列來保存發送的消息,而默認子線程中是沒有開啓Looper輪循器的,而消息隊列又是由Looper來進行管理的,因此是沒有辦法開啓的, 若是子線程想要開啓,須要初始化looper,而且調用loop.loopers開啓一個循環

若是簡歷中寫了AsyncTask,就看一下,沒寫的直接跳過上Rxjava

AsyncTask是什麼 AsyncTask是一種輕量級的異步任務類,它能夠在線程池中執行後臺任務,而後把執行的進度和最終結果傳遞給主線程並主線程中更新UI,經過AsyncTask能夠更加方便執行後臺任務以及在主線程中訪問UI,可是AsyncTask並不適合進行特別耗時的後臺任務,對於特別耗時的任務來講,建議使用線程池。

AsyncTask使用方法 三個參數 Params:表示後臺任務執行時的參數類型,該參數會傳給AysncTask的doInBackground()方法 Progress:表示後臺任務的執行進度的參數類型,該參數會做爲onProgressUpdate()方法的參數 Result:表示後臺任務的返回結果的參數類型,該參數會做爲onPostExecute()方法的參數 五個方法 onPreExecute():異步任務開啓以前回調,在主線程中執行 doInBackground():執行異步任務,在線程池中執行 onProgressUpdate():當doInBackground中調用publishProgress時回調,在主線程中執行 onPostExecute():在異步任務執行以後回調,在主線程中執行 onCancelled():在異步任務被取消時回調

AsyncTask引發的內存泄漏 緣由:非靜態內部類持有外部類的匿名引用,致使Activity沒法釋放 解決: AsyncTask內部持有外部Activity的弱引用 AsyncTask改成靜態內部類 Activity的onDestory()中調用AsyncTask.cancel()

結果丟失 屏幕旋轉或Activity在後臺被系統殺掉等狀況會致使Activity的從新建立,以前運行的AsyncTask會持有一個以前Activity的引用,這個引用已經無效,這時調用onPostExecute()再去更新界面將再也不生效。

AsyncTask並行or串行 AsyncTask在Android 2.3以前默認採用並行執行任務,AsyncTask在Android 2.3以後默認採用串行執行任務 若是須要在Android 2.3以後採用並行執行任務,能夠調用AsyncTask的executeOnExecutor();

AsyncTask內部的線程池 private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; sDefaultExecutor是SerialExecutor的一個實例,並且它是個靜態變量。也就是說,一個進程裏面全部AsyncTask對象都共享同一個SerialExecutor對象。

ListView+RecyclerView 既然RecyclerView在不少方面能取代ListView,Google爲何沒把ListView劃上一條過期的橫線? ListView採用的是RecyclerBin的回收機制在一些輕量級的List顯示時效率更高

ListView怎麼和ScrollView兼容? 方法一:重寫ListView, 覆蓋onMeasure()方法 方法二:動態設置listview的高度,不須要重寫ListView 方法三:在xml文件中,直接將Listview的高度寫死

listview怎麼優化? 1)、convertView複用,對convetView進行判空,當convertView不爲空時重複使用,爲空則初始化,從而減小了不少沒必要要的View的建立 2)定義一個ViewHolder,封裝Listview Item條目中全部的組件,將convetView的tag設置爲ViewHolder,不爲空時經過ViewHolder的屬性獲取對應組件便可 3)、當ListView加載數據量較大時能夠採用分頁加載和圖片異步加載

上拉加載和下拉刷新怎麼實現? 實現OnScrollListener 接口重寫onScrollStateChanged 和onScroll方法, 使用onscroll方法實現」滑動「後處理檢查是否還有新的記錄,若是有,調用 addFooterView,添加記錄到adapter, adapter調notifyDataSetChanged 更新數據;若是沒有記錄了,把自定義的mFooterView去掉。使用onScrollStateChanged能夠檢測是否滾到最後一行且中止滾動而後執行加載

listview失去焦點怎麼處理? 在listview子佈局裏面寫,能夠解決焦點失去的問題 android:descendantFocusability=」blocksDescendants」

ListView圖片異步加載實現思路? 1.先從內存緩存中獲取圖片顯示(內存緩衝) 2.獲取不到的話從SD卡里獲取(SD卡緩衝,,從SD卡獲取圖片是放在子線程裏執行的,不然快速滑屏的話會不夠流暢) 3.都獲取不到的話從網絡下載圖片並保存到SD卡同時加入內存並顯示(視狀況看是否要顯示)

你知道Listview裏有Button就點不動了你知道嗎? 緣由是button強制獲取了item的焦點,只要設置button的focusable爲false便可。

listview分頁加載的步驟? 一般實現分頁加載有兩種方式,一種是在ListView底部設置一個按鈕,用戶點擊即加載。另外一種是當用戶滑動到底部時自動加載。 當用戶滑動到底部時自動加載實現思路: 實現OnScrollListener 接口重寫onScrollStateChanged 和onScroll方法,使用onscroll方法實現」滑動「後處理檢查是否還有新的記錄,若是有,添加記錄到adapter, adapter調用 notifyDataSetChanged 更新數據;若是沒有記錄了,則再也不加載數據。使用onScrollStateChanged能夠檢測是否滾到最後一行且中止滾動而後執行加載.

ViewHolder內部類非得要聲明成static的呢? 由於非靜態成員類的實例會包含一個額外的指向外圍對象的引用,保存這份引用要消耗時間和空間,而且致使外圍類實例符合垃圾回收時仍然被保留。若是沒有外圍實例的狀況下,也須要分配實例,就不能使用非靜態成員類,由於非靜態成員類的實例必需要有一個外圍實例。

ScrollView嵌套ListView和GridView衝突的方法 重寫ListView的onMeasure方法,來自定義高度:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } 1 2 3 4 5 BaseAdapter四個關鍵方法的含義? 1) getCount() 返回數據源中數據的個數,若是該方法的返回值爲0,那麼適配器就不用生成佈局對象了,提升了程序性能 2)getItem(int position) 根據位置返回數據項 3)getItemId(int position) 返回數據項的位置 4)getView(int position, View convertView, ViewGroup parent)

RecyclerView滑動刪除原理實現? 兩種方法: 一種就是經過重寫RecyclerView的onTouchEvent()方法來檢測手勢的變化實現的,大體的流程以下: 一、根據手指觸摸的座標點找到對應Item的ViewHolder,進而獲得相應的Item佈局View。 二、手指繼續移動,在條件知足的狀況下,經過scrollBy()使Item佈局View內容跟隨手指一塊兒移動,固然要注意邊界檢測。 三、手指擡起時,根據Item佈局View內容移動的距離以及手指的滑動速度,判斷是否顯示刪除按鈕,進而經過startScroll()使Item佈局View自動滑動到目標位置。 四、點擊刪除按鈕則刪除對應Item,點擊其它區域則隱藏刪除按鈕。

另一種: 實現原理 主要是藉助 ItemTouchHelper.Callback 類來實現,咱們要關注的方法爲

  • getMovementFlags( )
  • onMove()
  • onSwiped()
  • onSelectedChanged()
  • clearView()
  • isLongPressDragEnabled()

首先自定義一個MyCallback類繼承 ItemTouchHelper.Callback ,定義兩個int變量dragFlags 與 swipeFlags並實現下方法。這個方法主要是爲了獲取咱們當前的事件是拖動仍是滑動

其餘: Android View刷新機制? 在Android的佈局體系中,父View負責刷新、佈局顯示子View;而當子View須要刷新時,則是通知父View來完成

RelativeLayout和LinearLayout性能比較? 1.RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,也會調用子View2次onMeasure 2.RelativeLayout的子View若是高度和RelativeLayout不一樣,則會引起效率問題,當子View很複雜時,這個問題會更加嚴重。若是能夠,儘可能使用padding代替margin。 3.在不影響層級深度的狀況下,使用LinearLayout和FrameLayout而不是RelativeLayout。

View和ViewGroup什麼區別? Android的UI界面都是由View和ViewGroup及其派生類組合而成的。其中,View是全部UI組件的基類,而ViewGroup是容納這些組件的容器,其自己也是從View派生出來的

自定義View優化策略 爲了加速你的view,對於頻繁調用的方法,須要儘可能減小沒必要要的代碼。先從onDraw開始,須要特別注意不該該在這裏作內存分配的事情,由於它會致使GC,從而致使卡頓。在初始化或者動畫間隙期間作分配內存的動做。不要在動畫正在執行的時候作內存分配的事情。 你還須要儘量的減小onDraw被調用的次數,大多數時候致使onDraw都是由於調用了invalidate().所以請儘可能減小調用invaildate()的次數。若是可能的話,儘可能調用含有4個參數的invalidate()方法而不是沒有參數的invalidate()。沒有參數的invalidate會強制重繪整個view。 另一個很是耗時的操做是請求layout。任什麼時候候執行requestLayout(),會使得Android UI系統去遍歷整個View的層級來計算出每個view的大小。若是找到有衝突的值,它會須要從新計算好幾回。另外須要儘可能保持View的層級是扁平化的,這樣對提升效率頗有幫助。 若是你有一個複雜的UI,你應該考慮寫一個自定義的ViewGroup來執行他的layout操做。與內置的view不一樣,自定義的view能夠使得程序僅僅測量這一部分,這避免了遍歷整個view的層級結構來計算大小。這個PieChart 例子展現瞭如何繼承ViewGroup做爲自定義view的一部分。PieChart 有子views,可是它歷來不測量它們。而是根據他自身的layout法則,直接設置它們的大小

音視頻 SurfaceView是什麼 ? 它繼承自類View,所以它本質上是一個View。但與普通View不一樣的是,它有本身的Surface。有本身的Surface,在WMS中有對應的WindowState,在SurfaceFlinger中有Layer。咱們知道,通常的Activity包含的多個View會組成View hierachy的樹形結構,只有最頂層的DecorView,也就是根結點視圖,纔是對WMS可見的。這個DecorView在WMS中有一個對應的WindowState。相應地,在SF中對應的Layer。而SurfaceView自帶一個Surface,這個Surface在WMS中有本身對應的WindowState,在SF中也會有本身的Layer。雖然在App端它仍在View hierachy中,但在Server端(WMS和SF)中,它與宿主窗口是分離的。這樣的好處是對這個Surface的渲染能夠放到單獨線程去作,渲染時能夠有本身的GL context。這對於一些遊戲、視頻等性能相關的應用很是有益,由於它不會影響主線程對事件的響應。但它也有缺點,由於這個Surface不在View hierachy中,它的顯示也不受View的屬性控制,因此不能進行平移,縮放等變換,也不能放在其它ViewGroup中,一些View中的特性也沒法使用。

SurfaceView優勢及缺點? 優勢:能夠在一個獨立的線程中進行繪製,不會影響主線程。使用雙緩衝機制,播放視頻時畫面更流暢

缺點:Surface不在View hierachy中,它的顯示也不受View的屬性控制,因此不能進行平移,縮放等變換,也不能放在其它ViewGroup中。SurfaceView 不能嵌套使用

SurfaceView中雙緩衝? 雙緩衝:在運用時能夠理解爲:SurfaceView在更新視圖時用到了兩張Canvas,一張frontCanvas和一張backCanvas,每次實際顯示的是frontCanvas,backCanvas存儲的是上一次更改前的視圖,當使用lockCanvas()獲取畫布時,獲得的其實是backCanvas而不是正在顯示的frontCanvas,以後你在獲取到的backCanvas上繪製新視圖,再unlockCanvasAndPost(canvas)此視圖,那麼上傳的這張canvas將替換原來的frontCanvas做爲新的frontCanvas,原來的frontCanvas將切換到後臺做爲backCanvas。例如,若是你已經前後兩次繪製了視圖A和B,那麼你再調用lockCanvas()獲取視圖,得到的將是A而不是正在顯示的B,以後你講重繪的C視圖上傳,那麼C將取代B做爲新的frontCanvas顯示在SurfaceView上,原來的B則轉換爲backCanvas。

TextureView是什麼? 在4.0(API level 14)中引入,與SurfaceView同樣繼承View, 它能夠將內容流直接投影到View中,它能夠將內容流直接投影到View中,能夠用於實現Live preview等功能。和SurfaceView不一樣,它不會在WMS中單首創建窗口,而是做爲View hierachy中的一個普通View,所以能夠和其它普通View同樣進行移動,旋轉,縮放,動畫等變化。值得注意的是TextureView必須在硬件加速的窗口中。它顯示的內容流數據能夠來自App進程或是遠端進程。從類圖中能夠看到,TextureView繼承自View,它與其它的View同樣在View hierachy中管理與繪製。TextureView重載了draw()方法,其中主要SurfaceTexture中收到的圖像數據做爲紋理更新到對應的HardwareLayer中。SurfaceTexture.OnFrameAvailableListener用於通知TextureView內容流有新圖像到來。SurfaceTextureListener接口用於讓TextureView的使用者知道SurfaceTexture已準備好,這樣就能夠把SurfaceTexture交給相應的內容源。Surface爲BufferQueue的Producer接口實現類,使生產者能夠經過它的軟件或硬件渲染接口爲SurfaceTexture內部的BufferQueue提供graphic buffer。

TextureView優勢及缺點?

優勢:支持移動、旋轉、縮放等動畫,支持截圖

缺點:必須在硬件加速的窗口中使用,佔用內存比SurfaceView高,在5.0之前在主線程渲染,5.0之後有單獨的渲染線程。

誰的性能更優? 這裏寫圖片描述

播放器應該選擇誰?

從性能和安全性角度出發,使用播放器優先選SurfaceView。 一、在android 7.0上系統surfaceview的性能比TextureView更有優點,支持對象的內容位置和包含的應用內容同步更新,平移、縮放不會產生黑邊。 在7.0如下系統若是使用場景有動畫效果,能夠選擇性使用TextureView

二、因爲失效(invalidation)和緩衝的特性,TextureView增長了額外1~3幀的延遲顯示畫面更新

三、TextureView老是使用GL合成,而SurfaceView能夠使用硬件overlay後端,能夠佔用更少的內存帶寬,消耗更少的能量

四、TextureView的內部緩衝隊列致使比SurfaceView使用更多的內存

五、SurfaceView: 內部本身持有surface,surface 建立、銷燬、大小改變時系統來處理的,經過surfaceHolder 的callback回調通知。當畫布建立好時,能夠將surface綁定到MediaPlayer中。SurfaceView若是爲用戶可見的時候,建立SurfaceView的SurfaceHolder用於顯示視頻流解析的幀圖片,若是發現SurfaceView變爲用戶不可見的時候,則當即銷燬SurfaceView的SurfaceHolder,以達到節約系統資源的目的

視頻編碼標準兩大系統是什麼?

視頻編碼標準有兩大系統:MPEG和ITU-T,以下 視頻編碼標準 MPEG標準由MPEG制定 MPEG-1 | MPEG-2 | (MPEG-3) | MPEG-4 | MPEG-7 | MPEG-21 ITU-T標準由VCEG制定 H.261 | (H.262) | H.263 | H.263v2 | H.264

什麼是音視頻編碼格式?什麼是音視頻封裝格式?

常見的AVI、RMVB、MKV、ASF、WMV、MP四、3GP、FLV等文件其實只能算是一種封裝標準。

一個完整的視頻文件是由音頻和視頻2部分組成的。H26四、Xvid等就是視頻編碼格式,MP三、AAC等就是音頻編碼格式。

例如:將一個Xvid視頻編碼文件和一個MP3視頻編碼文件按AVI封裝標準封裝之後,就獲得一個AVI後綴的視頻文件,這個就是咱們常見的AVI視頻文件了。

因爲不少種視頻編碼文件、音頻編碼文件都符合AVI封裝要求,則意味着即便是AVI後綴,也可能裏面的具體編碼格式不一樣。所以出如今一些設備上,同是AVI後綴文件,一些能正常播放,還有一些就沒法播放。

一樣的狀況也存在於其餘容器格式。即便RMVB、WMV等也不例外,事實上,不少封裝容器對音頻編碼和視頻編碼的組合方式放的很開,如AVI還能夠使用H.264+AAC組合,能夠在具體使用中本身體會。尤爲是MKV封裝容器,基本不管什麼樣的組合均可以!但通常MKV用的最多的就是H.264+AAC組合,此組合文件體積最小,清晰度最高。所以網上不少MKV視頻都是高清晰度的。

所以,視頻轉換須要設置的本質就是:A設置須要的視頻編碼、B設置須要的音頻編碼、C選擇須要的容器封裝。一個完整的視頻轉換設置都至少包括了上面3個步驟。

平時說的軟解和硬解,具體是什麼?

硬解就是硬件解碼,指利用GPU來部分代替CPU進行解碼,軟解就是軟件解碼,指利用軟件讓CPU來進行解碼。二者的具體區別以下所示:

硬解碼:是將原來所有交由CPU來處理的視頻數據的一部分交由GPU來作,而GPU的並行運算能力要遠遠高於CPU,這樣能夠大大的下降對CPU的負載,CPU的佔用率較低了以後就能夠同時運行一些其餘的程序了,固然,對於較好的處理器來講,好比i5 2320,或者AMD 任何一款四核心處理器來講,硬解和軟件的區別只是我的偏好問題了吧。  

軟解碼:即經過軟件讓CPU來對視頻進行解碼處理;而硬解碼:指不借助於CPU,而經過專用的子卡設備來獨立完成視頻解碼任務。曾經的VCD/DVD解壓卡、視頻壓縮卡等都隸屬於硬解碼這個範疇。而現現在,要完成高清解碼已經再也不須要額外的子卡,由於硬解碼的模塊已經被整合到顯卡GPU的內部,因此目前的主流顯卡(集顯)都可以支持硬解碼技術。

何爲直播?何爲點播?

直播:是一個三方交互(主播、服務器、觀衆),這個交互式實時的!儘管會根據選擇的協議不一樣而有一些延遲,但咱們仍認爲它直播是實時的!—>主播在本地發送音視頻給服務器(推流),觀衆從服務器實時解碼(拉流)收看收聽主播發送給服務器的音視頻(直播內容)。直播是不能快進的 點播:首先必定要明確的一點,點播不存在推流這一過程,你自己你的流已經早就推給服務器了,或者這麼說也不對,應該是你的音視頻早就上傳到了服務器,觀衆只須要在線收看便可,因爲你的音視頻上傳到了服務器,觀衆則能夠經過快進,快退,調整進度條等方式進行收看!

簡述推流、拉流的工做流程? 推流:在直播中,一方向服務器發送請求,向服務器推送本身正在實時直播的數據,而這些內容在推送到服務器的這一過程當中是以 「流」 的形式傳遞的,這就是「推流」,把音視頻數據以流的方式推送(或上傳)到服務器的過程就是「推流」!推流方的音視頻每每會很大,在推流的過程當中首先按照 aac音頻-編碼 和 h264視頻-編碼的標準把推過來的音視頻壓縮 ,而後合併成 MP4或者 FLV格式,而後根據直播的封裝協議,最後傳給服務器完成推流過程。

拉流:與推流正好相反,拉流是用戶從服務器獲取推流方給服務器的音視頻的過程,這就是「拉流」!拉流首先aac音頻-解碼 和 h.264視頻-解碼的內部把推過來的音視頻解壓縮,而後合成 MP4或者 FLV 格式,再解封裝,最後到咱們的客戶端與觀衆進行交互。

常見的直播協議有哪些?之間有什麼區別?

常見的直播協議有三種 RTMP、HLS、FLV…

1)RTMP:real time messaging protocol~實時傳輸協議,RTMP協議比較全能,既能夠用來推送又能夠用來直播,其核心理念是將大塊的視頻幀和音頻幀「剁碎」,而後以小數據包的形式在互聯網上進行傳輸,並且支持加密,所以隱私性相對比較理想,但拆包組包的過程比較複雜,因此在海量併發時也容易出現一些不可預期的穩定性問題。

2)FLV:FLV協議由Adobe公司主推,格式極其簡單,只是在大塊的視頻幀和音視頻頭部加入一些標記頭信息,因爲這種極致的簡潔,在延遲表現和大規模併發方面都很成熟。惟一的不足就是在手機瀏覽器上的支持很是有限,可是用做手機端APP直播協議卻異常合適。

3)HLS:蘋果原生:HTTP Live Streaming,遵循的是 HTTP 超文本傳輸協議,端口號8080,將視頻分紅5-10秒的視頻小分片,而後用m3u8索引表進行管理,因爲客戶端下載到的視頻都是5-10秒的完整數據,故視頻的流暢性很好,但也一樣引入了很大的延遲(HLS的通常延遲在10-30s左右)。

點播中常見的數據傳輸協議主要有哪些?

常見的點播協議:HLS,HTTP

何爲Nginx?有什麼特色? Nginx 是一個遵循 HTTP 協議的服務器!內存佔用少,併發能力強! 還有等等的優勢,可自行google

何爲homebrew?你用它安裝過什麼?經常使用命令有哪些? homebrew是一個 Mac系統下所獨有的套件管理器,我要作直播,須要 rtmp 和 nginx ,單獨安裝很複雜,只要在終端裏輸入簡單的安裝相應的套件命令便可完成安裝,複雜的過程都靠 homebrew 規避掉了! 我用它安裝過不少東西,好比nginx 搭建流媒體服務器等。 經常使用命令:brew install 、brew uninstall、brew search、brew list、brew update、brew help 等~

FFmpeg是什麼?

FFmpeg是一套用來記錄和轉換數字音視頻,並能將其轉化爲流的開源計算機程序。拉流和推流離不開 FFmpeg 的幫助!

RTMP、HLS協議各自的默認端口號是?

RTMP端口號:1935 HLS端口號 :8080

m3u8構成是?直播中m3u八、ts如何實時更新?

是一個索引地址/播放列表,經過FFmpeg將本地的xxx.mp4進行切片處理,生成m3u8播放列表(索引文件)和N多個 .ts文件,並將其(m3u八、N個ts)放置在本地搭建好的webServer服務器的指定目錄下,我就能夠獲得一個能夠實時播放的網址,咱們把這個m3u8地址複製到 VLC 上就能夠實時觀看! 在 HLS 流下,本地視頻被分割成一個一個的小切片,通常10秒一個,這些個小切片被 m3u8管理,而且隨着終端的FFmpeg 向本地拉流的命令而實時更新,影片進度隨着拉流的進度而更新,播放過的片斷不在本地保存,自動刪除,直到該文件播放完畢或中止,ts 切片會相應的被刪除,流中止,影片不會當即中止,影片播放會滯後於拉流一段時間

PS: FFmpeg推流至Nginx:能夠推兩種流:RTMP流,推流至rtmplive;HLS流,推流至hls;其中,HLS流表現較明顯,在nginx的臨時目錄下,直觀的可看到m3u8索引文件和N多個.ts文件。m3u8列表會實時更新,且會動態更改當前播放索引切片(.ts)。這種實時更新的機制,不會使得.ts文件長時間存在於Nginx服務器上,且當推流結束以後,該目錄下的內容會被所有清除,這樣無形中減緩了nginx服務器的壓力。另外,也闡釋了HLS這種流媒體播放相較RTMP延時較高的緣由。

說說你平時在播放過程當中作的優化工做 預加載,弱網優化,播放出錯重試機制,運營商劫持引發的起播慢,mediaserver的cpu佔有率很高,引發播放卡頓。起播時,只保留播放進程,kill 其餘進程 。

未完待續

相關文章
相關標籤/搜索