【6.0】動態權限、使用Builder模式來構建通知、取消了Apache HTTP客戶端、相機Camera變動爲Camera2.以前是先到先得,如今是按照優先級別使用、【7.0】權限更改;【8.0】通知(添加了對通知渠道的支持)、後臺限制執行、運行時權限、安裝未知應用的權限、懸浮窗【9.0】劉海屏適配、通知功能的變動、利用 Wi-Fi RTT 進行室內定位【10.0】存儲權限、定位權限、設備惟一標識符等html
Frame Animation:逐幀動畫,即順序播放事先作好的圖像,跟電影相似 。java
Tween Animation:補間動畫,經過對場景裏的對象不斷作圖像變換 ( 平移(0,0) ->(100,100)、縮放、旋轉 ) 產生動畫效果。面試
Property Animation:屬性動畫,補間動畫加強版,支持對對象執行動畫。(0,0) -> (100,100)spring
Transition Animation:過渡動畫,主要是實現Activity或View過渡動畫效果。數據庫
www.jianshu.com/p/c77032b3c…bootstrap
答:設計模式
**onCreate(Bundle savedInstanceState):**建立activity時調用。設置在該方法中,還以Bundle的形式提供對之前儲存的任何狀態的訪問! onStart():activity變爲在屏幕上對用戶可見時調用。 onResume():activity開始與用戶交互時調用(不管是啓動仍是從新啓動一個活動,該方法老是被調用的)。緩存
onPause():activity被暫停或收回cpu和其餘資源時調用,該方法用於保存活動狀態的,也是保護現場,壓棧吧! onStop():activity被中止並轉爲不可見階段及後續的生命週期事件時調用。 onRestart():從新啓動activity時調用。該活動仍在棧中,而不是啓動新的活動。安全
OnDestroy():activity被徹底從系統內存中移除時調用,該方法被 2.橫豎屏切換時候activity的生命週期markdown
簡單來講,Fragment能夠理解爲一個具備本身生命週期的控件,只不過這個控件又有點特殊,它有本身的處理輸入事件的能力,有本身的生命週期,又必須依賴於Activity,能互相通訊和託管。
1.主要目的是爲了給大屏幕(如平板電腦)上更加動態和靈活的UI設計提供支持。因爲平板電腦的屏幕比手機的屏幕大不少,所以可用於組合和交換的UI組件的空間更大,利用Fragment實現此類設計的時,就無需管理對視圖層次結構的複雜更改。
2.代碼複用。特別適用於模塊化的開發,由於一個Fragment能夠被多個Activity嵌套,有個共同的業務模塊就能夠複用了,是模塊化UI的良好組件。
3.Activity用來管理Fragment。Fragment的生命週期是寄託到Activity中,Fragment能夠被Attach添加和Detach釋放。
4.可控性。Fragment能夠像普通對象那樣自由的建立和控制,傳遞參數更加容易和方便,也不用處理系統相關的事情,顯示方式、替換、無論是總體仍是部分,均可以作到相應的更改。
5.Fragments是view controllers,它們包含可測試的,解耦的業務邏輯塊,因爲Fragments是構建在views之上的,而views很容易實現動畫效果,所以Fragments在屏幕切換時具備更好的控制。
自定義View三種方式,組合現有控件,繼承現有控件,繼承View
- 自定義View屬性:在res/values/下創建一個attrs.xml,用來自定義View的屬性
- 在View的構造方法中得到自定義的屬性:重寫CustomTitleView的構造函數,來獲取自定義的屬性
- 重寫onMesure
- 重寫onDraw:重寫onDraw函數,根據讀取到的自定義屬性,繪製出相應的控件
specMode = EXACTLY :設置肯定的數值或者說match_parent。
specMode = AT_MOST :將子佈局限制爲一個最大值內或者說warp_content。
specMode = UNSPECIFIED:表示子佈局要多大就有多大,實際開發中比較少用。
重寫onMesure方法主要是爲了解決: 咱們在使用自定義控件的時候,設置warp_content並無按照適當縮放的效果顯示出來,而是鋪滿顯示,這個和咱們預期的效果不一致。
在activity的attach方法裏面,會建立一個PhoneWindow。
在onCreate中調用setContentView,setContentView
是window
的一個抽象方法,真正實現類是PhoneWindow
:
@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
//1.初始化
//建立DecorView對象和mContentParent對象 ,並將mContentParent關聯到DecorView上
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();//Activity轉場動畫相關
}
//2.填充Layout
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);//Activity轉場動畫相關
} else {
//將Activity設置的佈局文件,加載到mContentParent中
mLayoutInflater.inflate(layoutResID, mContentParent);
}
//讓DecorView的內容區域延伸到systemUi下方,防止在擴展時被覆蓋,達到全屏、沉浸等不一樣體驗效果。
mContentParent.requestApplyInsets();
//3\. 通知Activity佈局改變
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
//觸發Activity的onContentChanged方法
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
複製代碼
核心方法就兩個:installDecor() 和 mLayoutInflater.inflate(layoutResID, mContentParent) ;
installDecor會建立一個DecorView
對象,該對象將做爲整個應用窗口的根視圖。而後配置不一樣窗口修飾屬性(style theme等)。
mLayoutInflater.inflate就是解析xml,深度優先地遞歸解析xml,一層層添加到root view上,最終返回root view.解析的部分大體包含兩點:
1.解析出View對象
2.解析View對應的Params,並設置給View。
答:
一:runOnUiThread;
二:handler post;
三:handler sendMessage;
四:view post;
www.jianshu.com/p/d3758eef1… www.jianshu.com/p/38015afcd… www.jianshu.com/p/555ffeb64…
View事件分發本質就是對MotionEvent事件分發的過程。即當一個MotionEvent發生後,系統將這個點擊事件傳遞到一個具體的View上
點擊事件的傳遞順序:Activity(Window)→ViewGroup→ View
事件分發過程由三個方法共同完成:
- dispatchTouchEvent:用來進行事件的分發。若是事件可以傳遞給當前View,那麼此方法必定會被調用,返回結果受當前View的onTouchEvent和下級View的dispatchTouchEvent方法的影響,表示是否消耗當前事件
- onInterceptTouchEvent:在上述方法內部調用,對事件進行攔截。該方法只在ViewGroup中有,View(不包含 ViewGroup)是沒有的。一旦攔截,則執行ViewGroup的onTouchEvent,在ViewGroup中處理事件,而不接着分發給View。且只調用一次,返回結果表示是否攔截當前事件
- onTouchEvent: 在dispatchTouchEvent方法中調用,用來處理點擊事件,返回結果表示是否消耗當前事件
Handler解決應用內的通訊和管理;包含handler、Looper、Message、MessageQueue、thread
在建立主線程時,會自動執行**
ActiityThread
類中的靜態方法main()
,而main()
方法內部會調用Looper.prepareMainLooper()
方法,爲主線程建立一個Looper對象
和一個MessageQueue對象
, 而後調用Looper.loop()
**消息循環方法取出消息
先獲取
Looper對象
, 而後獲取消息隊列對象MesageQueue
,再經過死循環,從消息隊列中獲取消息**queue.next()
,拿到消息就分發給對應handler的方法dispatchMessage(Message msg)
;**
將發送消息加入到消息隊列中,在加入前爲消息對象Message的target屬性設置指向當前的handler對象,在Looper.loop()取出消息隊列中的消息,就能夠找到對應的handler分發消息了.
多個;由於Handler能夠在Activity中new,在Service裏面也能夠new,而Activity所有都跑在了主線程裏面,這就證實了主線程中能夠有多個Handler。
經過查看ActivityThread的handleMessage的源碼能夠看出,Android是由事件驅動的,常見的觸摸和Activity的生命週期都是運行在Looper.loop()的控制之下,若是該循環中止了,那麼整個應用也中止了。
主線程中若是沒有looper進行循環,那麼主線程一運行完畢就會退出。那麼咱們還能運行APP嗎,顯然,這是不可能的,Looper主要就是作消息循環,而後由Handler進行消息分發處理,一旦退出消息循環,那麼你的應用也就退出了。
只有一個Looper;有一個ThreadLocal類,其中有一個ThreadLocalMap,由於一個線程跟一個ThreadLocalMap是綁定的,若是這個Map中存有當前Looper裏的sThreadLocal爲鍵的鍵值對,就不會再存儲Looper,反而而會拋異常了,由於sThreadLocal在全局是惟一的。
ThreadLocal 是一個線程內部的數據存儲類,經過它能夠在指定的線程中存儲數據,其餘線程則沒法獲取。
**做用:**ThreadLocal是解決線程安全問題一個很好的思路,它經過爲每一個線程提供一個獨立的變量副本解決了變量併發訪問的衝突問題。在不少狀況下,ThreadLocal比直接使用synchronized同步機制解決線程安全問題更簡單,更方便,且結果程序擁有更高的併發性。
**答:**爲了方便回收;WeakReference對應用的對象userInfoLocal是弱引用,不會影響到userInfoLocal的GC行爲。若是是強引用的話,在線程運行過程當中,咱們再也不使用userInfoLocal了,將userInfoLocal置爲null,但userInfoLocal在線程的ThreadLocalMap裏還有引用,致使其沒法被GC回收(固然,能夠等到線程運行結束後,整個Map都會被回收,但不少線程要運行好久,若是等到線程結束,便會一直佔着內存空間)。而Entry聲明爲WeakReference,userInfoLocal置爲null後,線程的threadLocalMap就不算強引用了,userInfoLocal就能夠被GC回收了。map的後續操做中,也會逐漸把對應的"stale entry"清理出去,避免內存泄漏。
**答:**對於Handler來講,若是咱們直接在AndroidStudio中建立一個非靜態內部類Handler,那麼Handler這一大片的區域會被AS標記爲黃色,這個應該不少人都遇到過吧。其實是由於這樣設置會形成內存泄露,由於每個非靜態內部類都會持有一個外部類的引用,那麼這裏也就產生了一個內存泄露的可能點,若是當Activity被銷燬時沒有與Handler解除,那麼Handler仍然會持有對該Activity的引用,那麼就形成了內存泄露。
**解決方法:**使用static修飾Handler,這樣也就成了一個靜態內部類,那麼就不會持有對外部類的引用了。而這個時候就能夠在Handler中建立一個WeakReference(弱引用)來持有外部的對象。只要外部解除了與該引用的綁定,那麼垃圾回收器就會在發現該弱引用的時候馬上回收掉它。
**答:**在ActivityThread.java裏有一個main()函數,它是Android每個應用最先執行的函數。
prepare是初始化,初始化了一個Looper。
而後又接着調用的Looper.loop()函數,這個loop()函數其實就是執行了那個for循環,它不斷的調用next()函數,經過調用next()函數去輪詢咱們的MessageQueue。
若是不調用prepare(),Looper沒有被初始化;若是不調用loop(),Looper的機制滾動不起來。因此,全部的執行必須先prepare(),而後再loop()。
由於主線程一啓動的時候,在main()函數中,由系統已經幫咱們完成了,咱們主線程中的全部代碼,全都運行在這兩個函數(prepare() 和 loop())之間。
全部的線程都必需要prepare()和loop(),若是子線程中想要進行Handler操做,就必須在子線程中執行prepare() 和 loop()。
答:均可以用以在子線程中發送Runnable對象的方法;Android中post()方法能夠直接在非UI線程中更新UI,不一樣與Handelr的Send類方法,須要進行切換;兩個方法在實現UI線程事件的時間上有所區別,postDelayed()方法用以延期執行,post則是當即執行;
handler.postDelay() 的實現是經過MessageQueue中執行時間順序排列,消息隊列阻塞,和喚醒的方式結合實現的
onReceive()
函數時10秒沒有處理完成,後臺爲20秒ContentProvider
的publish
在10s內沒進行完儘可能避免在主線程中作耗時操做。 多線程==>引出如何實現多線程,線程池的使用
data/anr/
目錄下生成一個文件traces.txt
Logcat
中查看**答:**Binder是一種進程間通訊機制, 採用C/S架構,Binder框架中主要涉及到4個角色Client、Server、Service Manager及Binder驅動,其中Client、Server、Service Manager運行在用戶空間,Binder驅動運行在內核空間,Client表明客戶端進程,Server表明客戶端進程提供各類服務,如音視頻等;Service Manager用來管理各類系統服務;Binder驅動提供進程間通訊的能力
Binder IPC 機制中涉及到的內存映射經過 mmap() 來實現,mmap() 是操做系統中一種內存映射的方法。內存映射簡單的講就是將用戶空間的一塊內存區域映射到內核空間。映射關係創建後,用戶對這塊內存區域的修改能夠直接反應到內核空間;反以內核空間對這段區域的修改也能直接反應到用戶空間。
冷啓動:當啓動應用時,後臺沒有該應用的進程,這時系統會從新建立一個新的進程分配給該應用,這個啓動方式就是冷啓動。
熱啓動:當啓動應用時,後臺已有該應用的進程(例:按home鍵回到桌面,可是該應用的進程是依然會保留在後臺,可進入任務列表查看),因此在已有進程的狀況下,這種啓動會從已有的進程中來啓動應用,這個方式叫熱啓動。
【題目】開始開發 APP 如何進行架構?
【題目】APP 工程模塊是如何劃分的?你是如何進行封裝的?
【題目】APP 是如何進行優化的?
【題目】知道 OOM 嗎?如何解決內存泄漏?
【題目】如何實現 Activity 與 fragment 的通訊?
Activity 如何傳遞數據到Fragment: 採用 Bundle
方式
Fragment 如何傳遞數據到 Activity:採用 接口回調
方式
答:(1)啓動的起點發生在Launcher活動中,啓動一個app說簡單點就是啓動一個Activity,那麼咱們說過全部組件的啓動,切換,調度都由AMS來負責的,因此第一步就是Launcher響應了用戶的點擊事件,而後通知AMS
(2)AMS獲得Launcher的通知,就須要響應這個通知,主要就是新建一個Task去準備啓動Activity,而且告訴Launcher你能夠休息了(Paused);
(3)Launcher獲得AMS讓本身「休息」的消息,那麼就直接掛起,並告訴AMS我已經Paused了;
(4)AMS知道了Launcher已經掛起以後,就能夠放心的爲新的Activity準備啓動工做了,首先,APP確定須要一個新的進程去進行運行,因此須要建立一個新進程,這個過程是須要Zygote參與的,AMS經過Socket去和Zygote協商,若是須要建立進程,那麼就會fork自身,建立一個線程,新的進程會導入ActivityThread類,這就是每個應用程序都有一個ActivityThread與之對應的緣由;
(5)進程建立好了,經過調用上述的ActivityThread的main方法,這是應用程序的入口,在這裏開啓消息循環隊列,這也是主線程默認綁定Looper的緣由;
(6)這時候,App尚未啓動完,要永遠記住,四大組建的啓動都須要AMS去啓動,將上述的應用進程信息註冊到AMS中,AMS再在堆棧頂部取得要啓動的Activity,經過一系列鏈式調用去完成App啓動;
Gilde的優勢 一、圖片佔用內存回收及時,能減小因內存不足形成的崩潰,生命週期和Activity/Fragment一致。 (重要的特性) 二、默認Bitmap格式是RGB_565,減小內存資源佔用。 三、glide比universal-image-loader佔用的內存要小一些。 四、圖片顯示效果爲漸變,更加平滑。 五、glide能夠將任何的本地視頻解碼成一張靜態圖片。 六、支持 Gif、WebP、縮略圖
Imageloader分爲二級緩存:內存緩存和本地文件緩存(也有人說是三級緩存,第三級網絡緩存。可是博主認爲網絡部分不該算在緩存部分。純屬我的意見請勿噴!) 這篇博文我就和你們一塊兒來了解一下內存緩存部分。
**標準廣播:**徹底異步執行的廣播,當發出廣播後,廣播接收器幾乎會在同一時刻接收到廣播消息,因此沒有前後順序可言,效率比較高,沒法被截斷。
**有序廣播:**同步執行的廣播,廣播發出後,會有一個廣播接收器接收廣播消息,當這個廣播接收器中的邏輯執行完畢後廣播纔會繼續傳遞。有前後順序,優先級較高的接收器先收到廣播消息而且能夠截斷正在傳遞的廣播,使得後面的接收器沒法收到廣播消息。
**系統廣播:**Android內置不少系統級別廣播,如手機開機後發一條廣播,電池電量發生變化發一條廣播等等。
Hibernate是一種ORM框架,全稱爲 Object_Relative DateBase-Mapping**,在Java對象與關係數據庫之間**創建某種映射,以實現直接存取Java對象!
咱們使用Hibernate框架就不用咱們寫不少繁瑣的SQL語句,從而簡化咱們的開發!
startActivityForResult方法可以起效:standard和singleTop
startActivityForResult方法不可以起效:singleTask和singleInstance
www.jianshu.com/p/7e70ee765… blog.csdn.net/zy_jibai/ar…
**標準模式(standard):**每次啓動一個標準模式的Activity都會從新建立一個新的實例,無論這個Activity以前是否已經存在實例,一個任務棧中能夠有多個實例,每一個實例也能夠屬於不一樣的任務棧,誰啓動了這個Activity,那麼這個Activity實例就運行在啓動它的那個Activity所在的棧中 。
**棧頂複用模式(singleTop):**在這種模式下,若是新啓動的Activity已經位於任務戰的棧頂,那麼此Activity不會被從新建立,只會從新調用 onNewIntent 方法,這個Activity的onCreate、onStart都不會被系統調用。若是新Activity實例已經存在但不在棧頂,那麼從新建立 Activity 並放入棧頂。
**棧內複用模式(singleTask):**這是一種單實例模式,一個棧中同一個Activity只存在惟一一個實例,不管是否在棧頂,只要存在實例,都不會從新建立,和 singleTop 同樣會從新調用 onNewIntent 方法。
**單例模式(singleInstance):**這是一種增強的singleTask模式,它除了具備singleTask模式的全部特性外,還增強了一點,那就是此種模式的Activity只能單獨地位於一個任務棧中,不一樣的應用去打開這個activity 共享公用的同一個activity。他會運行在本身單獨,獨立的任務棧裏面,而且任務棧裏面只有他一個實例存在。
首先Activity.this和getApplicationContext()返回的不是同一個對象,一個是當前Activity的實例,一個是項目的Application的實例,這二者的生命週期是不一樣的,它們各自的使用場景不一樣,this.getApplicationContext()取的是這個應用程序的Context,它的生命週期伴隨應用程序的存在而存在;而Activity.this取的是當前Activity的Context,它的生命週期則只能存活於當前Activity,這二者的生命週期是不一樣的。getApplicationContext() 生命週期是整個應用,當應用程序摧毀的時候,它纔會摧毀;Activity.this的context是屬於當前Activity的,當前Activity摧毀的時候,它就摧毀。
blog.csdn.net/shenggaofei… blog.csdn.net/xiankog/art…
SharedPreference 相關修改使用 apply 方法進行提交會先寫入內存,而後異步寫入磁盤,
commit方法是直接寫入磁盤。若是頻繁操做的話 apply 的性能會優於 commit,apply會將最後修改內容寫入磁盤。 可是若是但願馬上獲取存儲操做的結果,並據此作相應的其餘操做,應當使用 commit。
juejin.cn/post/684490… www.jianshu.com/p/eca3d9371…
service是否在main thread中執行,service裏面是否能執行耗時的操做? 默認狀況,若是沒有service所運行的進程,Service和Activity是運行在當前app所在進程中的main thread裏面 service裏面不能執行耗時的操做(網絡請求,拷貝數據庫,大文件) 特殊狀況,能夠在清單文件中配置service所在的進程,讓service在另外的進程中執行。
Activity怎麼和Service綁定,怎麼在Activity中啓動本身對應的Service? Activity經過bindService(Intent service,ServiceConnection conn,int flags)跟Service進行綁定,當綁定成 功的時候ServiceService會將代理對象經過會調的方式傳給conn,這樣咱們就拿到了Service提供的服務代理對象。 在Activity中能夠經過startService和bindService方法啓動Service。通常狀況下若是想獲取Service的服務對象 那麼確定須要bindService()方法,好比音樂播放器,第三方支付等。若是僅僅只是爲了開啓一個後臺任務那麼可 以使用startService()方法。
mvc:業務邏輯、數據、界面分離的一種模式,簡單的來講,就是經過controller來操做model層的數據,而且返回給view顯示。
activity不是標準的controller,隨着界面邏輯交互的複雜度提高,activity類的職責不斷增長,變得臃腫。 view和model相互耦合,不利於開發。
mvp:主要是提出了presenter層,做爲view和model之間溝通的橋樑。
程序邏輯放在presenter中處理,徹底將view和model進行了分離,不容許他們之間溝通。
mvvm:主要是將presenter改成了viewmodel,和mvp相似,不一樣的是viewmodel跟view和model進行雙向綁定。
使用了data binding
定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則全部依賴於它的對象都會獲得通知並自動更新。
Spring Boot 是 Spring 開源組織下的子項目,是 Spring 組件一站式解決方案,主要是簡化了使用 Spring 的難度,簡省了繁重的配置,提供了各類啓動器,開發者能快速上手。
無代碼生成和xml配置
Spring Boot 的核心配置文件是 application 和 bootstrap 配置文件。
application 配置文件這個容易理解,主要用於 Spring Boot 項目的自動化配置。
bootstrap 配置文件有如下幾個應用場景。
啓動類上面的註解是@SpringBootApplication,它也是 Spring Boot 的核心註解,主要組合包含了如下 3 個註解:
@SpringBootConfiguration:組合了 @Configuration 註解,實現配置文件的功能。
@EnableAutoConfiguration:打開自動配置的功能,也能夠關閉某個自動配置的選項,如關閉數據源自動配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。
@ComponentScan:Spring組件掃描。
Starters能夠理解爲啓動器,它包含了一系列能夠集成到應用裏面的依賴包,你能夠一站式集成 Spring 及其餘技術,而不須要處處找示例代碼和依賴包。如你想使用 Spring JPA 訪問數據庫,只要加入 spring-boot-starter-data-jpa 啓動器依賴就能使用了。
面試題總結網站: www.cnblogs.com/marsitman/p… www.jianshu.com/p/c93965357… blog.csdn.net/xiaohulunb?… how2j.cn/k/j2se-inte… www.jianshu.com/p/cfac5c131… www.jianshu.com/p/d256d8e3d… www.jianshu.com/p/5eb9ab39d…
刷題網站: 牛客網劍指offer,聽網上說的刷了3遍,後來感受時間耗的有點多,兩遍就行加深記憶 www.nowcoder.com/ta/coding-i… leetcode熱題HOT100: leetcode-cn.com/problemset/… 基礎知識網站: java基礎課程: www.feiyangedu.com/referer/ag2… Linux經常使用命令: www.cnblogs.com/yjd_hycf_sp…