v:* {behavior:url(#default#VML);} o:* {behavior:url(#default#VML);} w:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);}javascript
Normaljava
0android
falsegit
7.8 磅程序員
0github
2web
false面試
false正則表達式
false算法
EN-US
ZH-CN
X-NONE
/* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-priority:99; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:等線; mso-ascii-font-family:等線; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:等線; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:等線; mso-hansi-theme-font:minor-latin; mso-font-kerning:1.0pt;} table.MsoTableGrid {mso-style-name:網格型; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-priority:39; mso-style-unhide:no; border:solid windowtext 1.0pt; mso-border-alt:solid windowtext .5pt; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-border-insideh:.5pt solid windowtext; mso-border-insidev:.5pt solid windowtext; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:等線; mso-ascii-font-family:等線; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:等線; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:等線; mso-hansi-theme-font:minor-latin; mso-font-kerning:1.0pt;}
Android技術面(注意時間的把握與控制) **
1**、自我介紹一下吧(一兩分鐘內,簡短介紹學習、項目經歷) **
我是來自廣東工業大學信息工程學院的吳煥楠,面目一新的煥,木字邊加東南西北的楠,我來應聘的崗位是android開發工程師。大二開始自學android開發,看的是淘寶網買的一套黑馬程序員的視頻教程,後來又在菜鳥窩官網學習了一套叫作《菜鳥商城》的實戰視頻教程,後期主要是靠實習和看書,看博客來提高本身的技術水平。
2**、在什麼地方實習過?實習多久?平時主要作什麼?離職了嗎?爲何離職? **
是這樣的,我是在今年3月份開始在悅乎網絡科技有限公司實習的,一直到九月份才離職,一共工做了6個月。這家公司是一家創業型公司,規模比較小,可是基本全部功能模塊都是本身獨立完成的,這樣能夠有更多鍛鍊本身的機會。可是畢竟是實習,薪水只能知足於生活費用,如今以爲本身的水平已經有必定提高,所以想獲得貴公司的承認。
平時主要的任務就是負責開發《師兄幫幫》APP的各類功能模塊的調研,開發以及平常的升級與維護。
3**、能不能簡單介紹一下你作過的APP?開發週期?你作的項目,說一下優缺點,有什麼想改進的地方? **
《師兄幫幫》是一款垂直社交應用平臺,這款產品主打是大學生,裏面有20萬份資料供用戶閱讀查看和下載。用戶能夠在這個平臺上發佈問題或者須要,也能夠進行搶單,解決問題之後就有相應的報酬。
**開發週期:**一個星期一個小版本,一個月一個大版本
優勢是:技術方面:在架構設計方面比較混亂,沒有用到一些比較新的架構。細節上面:尚未適配android6.0的動態權限。
非技術方面:界面比較清晰易懂,但就是功能過於單一。限制太多,不少功能須要花錢,並且用戶之間的互動比較少。至於app的盈利模式,公司規定不能向外透露。
4**、你在開發這個APP的時候你遇到過的技術難點有什麼?你是怎麼解決的?(重點問題,必定要準備) **
*******注意點: **
1**、說到實現一個功能的時候,先說本身想辦法,調研。實在找不到解決方案的時候,就說網上已經有成熟的解決方案。最好能說說找到了什麼方案,最好能說一些外國的SDK或者庫,給人一種比較牛逼的感受。 **
2**、最好在說的時候突出一下團隊合做,突出本身有提早調研過,計劃好纔開始寫代碼,實在是按時完成不了的就說本身是另外找時間加班完成的。 **
** **
0、內存泄漏問題
解決:
先介紹內存泄漏:用例子說明,個人手錶明app所能使用的內存,手裏面可以放不少東西。好比我手裏有鑰匙,洋娃娃。而洋娃娃須要揚聲器才能工做,那麼洋娃娃和揚聲器之間就有了引用的關係。一旦我扔掉了洋娃娃,就會有垃圾回收器來回收。可是意外的是,個人鑰匙和洋娃娃黏在了一塊兒,阻止了我扔掉洋娃娃。致使洋娃娃不會被回收掉。內存泄漏就是外部的引用指向了原本應該被回收的對象,形成對象不能被釋放,致使了內存泄漏。
項目中,爲了app的特效,打算作水波紋效果,可是這是5.0以上原有的,如下版本須要本身手動實現ViewGroup,後來發現了github上面的水波紋效果控件。可是致使app變卡,初步判定是內存泄漏致使的。使用LeakCanary來進行檢測內存泄漏(結合Demo),最終分析出是BitMap對象沒有recycle致使。Demo分析,靜態變量比較特殊,是GC root的一種,回收器只會回收非GC root的對象。解決辦法:手動設置爲null,或者使用弱引用。
LeakCanary檢測內存泄漏的原理是利用虛引用(虛引用不會影響回收,即虛引用不會對象的生命週期,回收取決於對象是否還存在強引用)對被測對象打一個標記,當對象回調銷燬(onDestory)以後,一旦判斷到這個弱引用還存在的話,就說明對象不能被正確回收,形成了內存泄漏。而後利用API把堆內存的信息dump出來,而且彈出通知提醒用戶,最終把信息顯示到界面上面。
一、
APP內部查閱資料的問題:資料有word、excel、ppt、PDF、圖片等格式。因爲PDF和大圖的查看網上有不少成熟的解決方案。可是谷歌官方並無在android原平生臺查看office文檔的功能,相對來講IOS的瀏覽器內核Safari是支持直接打開office文檔的。
解決:原本打算本身實現,可是發現工做量很大,所以只能找第三方解決方案。當時考慮過使用Apache的POI,可是發現這個庫主要是java方向的,對於android的兼容性作得不是很好,引入的時候出現過不少問題。也考慮過使用韓國的一款office SDK,叫作北極星Office,可是後來考慮到這個SDK收費太貴因此沒有使用。最後是決定採用使用Web Office服務,有服務動態生成office文檔的url,用android的WebView來加載和瀏覽。
二、
第二個要說的就是沉浸式狀態欄的實現。這個問題比較尷尬,由於咱們的標題欄是白色的,所以若是直接設置狀態欄的顏色爲白色的話,那麼原有的狀態欄上面的文字是白色的話就看不見了。
解決:目前來講只有小米、魅族以及android6.0以上才提供了設置狀態欄字體顏色的API。考慮到兼容性問題,只能參考市面上的一些app,把狀態欄設置爲半透明的黑色。使用了github上面的一個開源庫system bar tint,而且在app主題中開啓了透明狀態欄。
三、
短信驗證碼的自動填寫。
解決:使用Content Observer去觀察短信數據庫的收件箱,當有新的短信進來的時候,就經過正則表達式去獲取短信中的驗證碼,而且經過handler把結果傳遞到UI中。四個連續數字(\d{4})
四、
動態庫文件(so文件)衝突:因爲當時想引入Fresco圖片緩存框架,可是後來發現因爲Fresco框架對不一樣架構的平臺的支持得很是好,提供了全部平臺的so包,可是這樣會致使app不能正確加載其餘庫(如短信驗證SDK)的so庫,從而引起crash。
解決:當時是看到Stack Overflow上的一篇博客介紹,經過配置APP的gradle腳本文件,使得app只輸出armabi架構的so包,成功解決問題。
五、
實現防止多終端登陸同一個帳號的時候,服務器須要知道用戶是否正在登陸app。
解決:經過後臺開一個Service,每隔一段時間去訪問服務端的一個心跳接口,從而告訴服務端app的某個帳號正在使用。當時也考慮過其餘的解決方案,可是這個惟有客戶端去輪詢才能實現。
六、
使用第三方SDK時,例如融雲即便聊天、Ping++的時候,遇到問題通常都是經過提交工單的方式去尋求解決。
5**、你說你看過好多書,能不能簡單介紹一下你看過什麼書?平時看什麼博客?本身寫過博客嗎? **
《android源碼設計模式解析與實戰》,這是一本介紹了設計原則、設計模式以及android源碼的一本書。
《android羣英傳》,《android開發藝術探索》,《android開發從小工到專家》,這些都是android方面的技術進階書籍,從各個方面介紹android開發中的一些常見的難點。
《android神兵利器》,主要介紹了git、android studio等工具的使用,還沒看完。
平時看的博客主要來源於CSDN,微信公衆號等,本身有在簡書上面寫技術博客以及筆記。
6**、你會不會使用反射技術?你是怎麼理解這個技術的?在什麼地方用過? **
我對反射技術的理解就是,反射就是把Java類中的各類成分經過java的反射API映射成相應的Java類,獲得這些類之後就能夠對其進行使用。好比方法,構造方法,成員變量,類型,包等。
直接用到反射技術的很少,通常都是間接用到比較多。好比:
一、android中的經過讀取佈局文件的信息,而後利用反射來構造各類控件的對象。
二、使用開源ORM數據庫框架的時候,是經過反射的方式來進行java Bean和表的映射的。
三、Gson在解析JSON而且生成Bean對象的時候利用了反射技術。
7**、什麼是設計模式?你知道哪些設計模式?簡單介紹一下吧 **
設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。
單例模式,主要用在一些資源消耗比較多的類身上,比較典型的實現由DCL方式、枚舉、靜態內部類來實現。例子有
單例模式的DCL失效問題:虛擬機容許指令的亂序執行,當單例實例化的時候,實際上會執行了三個步驟:
給單例實例分配內存空間
調用單例實例的構造函數,初始化一些字段
將單例實例對象指向分配的內存空間(sInstance不爲null)
二、3兩步的執行順序是不肯定的,所以若是在多線程的狀態下,線程A執行了3之後,線程B立刻來取走實例,就是報錯(由於第二部的初始化尚未完成)
Builder模式,主要是用做一些複雜類的構建,而且通常支持連點操做。例子:
Adapter模式:這種模式主要是解決接口不兼容的問題。例子:
咱們經常使用的ListView、RecycleView等,就使用了adapter模式設計,這樣作分離了ListView顯示視圖,Adapter提供數據以及操做的功能,負責單一職責原則。
觀察者模式:這種模式是主要有被觀察者、觀察者組成,當被觀察者的觀察行爲發上變化的時候,觀察者能夠立刻作出相應處理。例子:
Content Observer
RXJava
ListView、RecycleView在設置Adapter的時候也註冊了數據觀察者,當用戶調用notifyDateSetChange等方法的時候,這些觀察者就會通知這些控件去從新刷新視圖。
工廠模式:主要是定義了一個對象建立的接口,具體產生什麼類由用戶去實現。例子:
裝飾者模式:動態地給一個對象添加一些額外的功能。例子:應用:IO流,ContextWrapper等。
8**、Java與JS的交互**
一、Java調用JS:直接利用WebView加載URL便可:webview.loadUrl("javascript:method("+參數+")");
二、WebView設置使能JS,建立JS Interface,設置到WebView當中。JS經過中window.appInterface.buy(id);調用Java方法。
9**、簡述一下android的消息傳遞機制吧。 **
Android中的消息機制主要是指Handler的運行機制。Handler是進行線程切換的關鍵,在主線程和子線程之間切換隻是一種比較特殊的使用情景而已。其中消息傳遞機制須要瞭解的東西有Message、Handler、Looper、Looper裏面的MessageQueue對象。咱們能夠把整個消息機制看做是一條流水線。其中:
app在啓動的時候,也就是執行ActivityThread的main方法的時候,會爲主線程建立Looper,而且啓動整個app的消息循環,同時保證app不會立馬退出。
另外,子線程之間也能夠利用Handler進行通訊,甚至是子線程能夠經過Handler發消息給主線程。前提條件是子線程沒有關聯Looper,所以必須手動建立Looper而且啓動消息循環。
10**、簡述一下android的事件傳遞機制吧。遇到過(滑動)事件衝突嗎?你是怎麼解決的? **
事件老是從上往下進行分發,即先到達Activity,再到達ViewGroup,再到達子View,若是沒有任何成員消耗事件的話,事件會順着路徑往回傳遞。
遇到過事件衝突:就是ViewPager其中一個Pager上面的Banner,當Banner還沒滑到最後一頁的時候,應該請求ViewPager不要攔截本身的滑動事件;當Banner滑動到最後一頁的時候,要請求ViewPager去攔截本身的滑動事件,從而使得ViewPager可以跟Banner配合工做。
結合本身的Demo說說,舉例子:爺父子之間傳遞蘋果
11**、簡要說說View的工做機制。有自定義過View嗎?簡要說說。 **
View的工做機制(View的繪製流程)主要包括測量(Measure)和繪製(Draw),而對於ViewGroup來講還包括佈局(Layout)。
一、測量主要是根據用戶指定的測量大小以及模式經過setMeasuredDimension方法去設置View的大小。精確模式下須要返回用戶指定的大小。最大值模式以及不明確指定的模式下,須要提供默認大小,在最大值模式下須要返回二者的最小值。
二、繪製主要是經過一些畫圖API好比畫布畫筆,在View區域上面動態畫一些東西。
三、佈局主要是自定義ViewGroup的時候實現的,主要是控制各個子View在ViewGroup的位置以及他們之間的位置關係。
把《師兄幫幫》那個錄音按鈕給面試官看
12**、有沒有(參與)寫過(開源)框架? **
雖然我沒有在GitHub上面參與或者發表過開源項目,感受本身想傳上去,可是發現已經有實現了,可是我常常關注GitHub上面看一些不錯的開源項目和控件,好比說BGARefreshLayout、BaseRecyclerViewAdapterHelper、代碼家以及各類自定義控件等。日常也有關注一些android開發相關的微信公衆號,好比徐宜生、郭霖、android開發技術前線等,以及簡書、CSDN等一些大牛的博客,平時本身也有在簡書上面用MD來寫一些技術文章。
13**、有沒有關注一些新技術? **
RXJava:
一個異步請求庫,核心就是異步。利用的是一種擴展的觀察模式,被觀察者發生某種變化的時候,能夠經過事件(onNext、onError、onComplete)等方式經過觀察者。RXJava同時支持線程的調度和切換,用戶能夠指定訂閱發生的線程以及觀察者觸發的線程。
Retrofit 2.0:
經過註解的方式來指定URL、請求方法,實質上底層是經過OKHttp來實現的。
Dagger 2:一個依賴注入框架
HotFit:淘寶的Dexposed(兼容性很差,利用AOP面向切面編程實現)、阿里巴巴的AndFix(Dexposed從Method入手,可是AndFix從Field入手,不須要重啓),QQ空間的ClassLoader(虛擬機加載類以前,經過反射去修復有問題的Dex文件),微信的Tinker(沒有了解過,由於以前的手機用不了)、Nuwa(須要重啓)
插件式開發:核心是動態加載技術。當app愈來愈大的時候,經過插件化來減輕應用的內存以及CPU,還能夠實現熱插拔,實現動態修復和更新。
大概瞭解,須要用到的技術:反射、動態代理、類加載器原理等。插件開發是開發者經過將插件代碼封裝成Jar或者Apk文件放在網絡或者本地。在宿主app中加載而且調用插件中的方法。
14**、看過什麼框架?源碼?原理?有沒有本身寫過框架? **
**網絡請求框架的基本流程: **
一、首先build request參數
二、由於不能在主線程請求HTTP,因此你得有個Executor或者線程
三、enqueue後,經過線程去執行請求,把Request對象經過字節流輸出
四、獲得服務器數據後,獲取返回的輸入字節流,經過反序列化轉換成需
要的實體對象,最後經過callback回調給客戶端,同時還要實現線程切換
**Retrofit****的一些優勢: **
一、類型安全:經過指定泛型來實現
二、可擴展性強,能夠適應不一樣的業務需求
三、簡潔高效:經過註解的方式來實現網絡請求,大大減小了代碼量
四、高度解耦,內部經過Adapter模式適配不一樣的框架,好比RXJava等
**Retrofit****源碼流程概述: **
一、先經過Builder模式去構造Retrofit對象,其中Retrofit只是外觀模式包裝的一個對象,全部基本功能都經過Retrofit來對外提供。構造Retrofit的內部構造了OkHttpClient對象,而且構建了CallbackExecutor對象,用來處理請求。同時也爲Retrofit指定了Converter。
二、爲咱們的請求接口建立動態代理對象,當這個對象的方法被調用的時候,會被攔截,而且經過ServiceMethod類去經過反射的方式去獲取這個對象上面的註解,經過這些註解獲取網絡請求方法、請求體等,最後構造出OKHttpCall對象、RequestConverter以及ResponseConverter,這兩個Converter分別是表明把請求對象、返回對象進行轉換,例如轉換成JSON、XML等。(注意:因爲經過反射獲取對象的註解是耗時而且消耗性能的,ServiceMethod內部有作緩存,解析過就直接複用)
三、當咱們調用Call對象進行enqueue或者execute的時候,內部是把OKHttpCall轉換成CallAdapter,分別適配:RxJava, Java8, Guava還有一個Retrofit默認的回調。
四、把請求分發給CallbackExecutor對象執行,CallbackExecutor內部實際上是調用OkHttp的一些相關方法進行請求。請求執行的時候經過RequestConverter進行轉換。
五、請求返回的時候,判斷返回碼的類型,經過ResponseConverter對象把返回的字節流轉換成實體對象,最後經過Handler機制post一個Runnable把Callback回調給主線程,刷新界面等操做。若是是使用RXJava的話,還能夠很方便地先去指定子線程進行數據轉換再返回主線程進行界面刷新。
**Retrofit****的一些功能擴展: **
一、經過自定義RequestConverter以及ResponseConverter進行數據網絡傳輸的加密、解密。
二、能夠經過自定義線程池來維護請求隊列,適應具體的業務需求。好比先進先出、後進先出等。
三、經過Adapter模式(CallbackAdapter)能夠利用不一樣的框架實現不一樣的回調代碼,好比RXJava、Java八、Guava等。
四、經過不一樣Converter實現Request以及Resource適應不一樣的協議,好比JSON、XML等。
主流的網絡請求框架
1**、**HttpURLConnection:在android4.4中已經替換成OKHttp了。
2**、**HttpClient:API數量比較多,使得咱們很難在不破壞兼容性的
狀況下對它進行升級和擴展維護成本較高,android5.0廢棄,6.0刪除。
3**、**Volley:已經中止更新。Android2.2如下版本使用HttpClient、
android2.2以上版本使用HttpURLConnection實現。可是相對來講擴
展性比Okhttp較低。
4**、**OkHttp:支持自定義請求頭、支持通常的請求方法、文件上傳
下載、圖片加載、IP自動重連、Gzip、SPDY、鏈接池、HTTP緩存等。
Retrofit:和Volley框架的請求方式很類似,底層網絡請求採用okhttp
(效率高,android4.4底層採用okhttp),採用註解方式來指定請求方
式和url地址,減小了代碼量。
主流的圖片加載框架
1.、Picasso:和Square的網絡庫一塊兒能發揮最大做用,由於Picasso能夠選擇將網絡請求的緩存部分交給了okhttp實現。 2.、Glide:模仿了Picasso的API,並且在他的基礎上加了不少的擴展(好比gif等支持),支持圖片流,所以在作愛拍之類的視頻應用用得比較多一些。 3.、Fresco:Fresco中設計有一個叫作image pipeline的模塊。它負責從網絡,從本地文件系統,本地資源加載圖片。 爲了最大限度節省空間和CPU時間,它含有3級緩存設計(2級內存,1級文件)。Fresco中設計有一個叫作Drawees模塊, 方便地顯示loading圖,當圖片再也不顯示在屏幕上時,及時地釋放內存和空間佔用。
Fresco是把圖片緩存放在了Ashmem(系統匿名內存共享區)
無論發生什麼,垃圾回收器都不會自動回收這些 Bitmap。當 Android 繪製系統在渲染這些圖片,Android 的系統庫就會把這些Bitmap 從 Ashmem 堆中抽取出來,而當渲染結束後,這些Bitmap 又會被放回到原來的位置。若是一個被抽取的圖片須要再繪製一次,系統僅僅須要把它再解碼一次,這個操做很是迅速。
圖片的三級緩存
當app須要使用圖片的時候,先到內存緩存去取,由於內存緩存速度最快。若是內存緩存沒有,再去本地緩存取,若是都沒有,就到網絡獲取。獲取之後分別寫入內存緩存以及本地緩存。
本身寫過圖片加載框架:
概述:利用組合設計模式,圖片加載功能在ImageLoader集中對外公開,ImageLoader是統籌了圖片下載器,圖片緩存等功能。
ImageLoader
ImageDownloaderer
ImageCache
ImageLoader
ImageLoader
遇到的問題:
一、
使用LruCache代替弱(軟)引用存儲,由於API9之後GC會更傾向於回收持有弱引用的對象。LruCache是android提供的一個緩存工具類,其算法是最近最少使用算法。它把最近使用的對象用「強引用」存儲在LinkedHashMap中,而且把最近最少使用的對象在緩存值達到預設定值以前就從內存中移除。其在API12被引進,低版本能夠用support包中的類。
二、
圖片的錯位問題。經過給ImageView打一個url標記,每次設置顯示圖片的時候先判斷Bitmap是否對應某一個ImageView。
三、
url做爲鍵值對中的鍵問題,使用MD5算法把url轉爲MD5字符串。
15**、網絡優化、網絡安全問題。**
爲何要作緩存,或者說有什麼好處?
一、減小服務器負荷,下降延遲提高用戶體驗。
二、複雜的緩存策略會根據用戶當前的網絡狀況採起不一樣的緩存策略,好比在2g網絡不好的狀況下,提升緩存使用的時間;
三、不用的應用、業務需求、接口所須要的緩存策略也會不同,有的要保證數據的實時性,因此不能有緩存,有的你能夠緩存5分鐘,等等。你要根據具體狀況所需數據的時效性狀況給出不一樣的方案。固然你也能夠所有都同樣的緩存策略,看你本身。
網絡優化建議點:
一、鏈接複用節省鏈接創建時間,如開啓keep-alive
二、不用域名,用IP直連省去DNS解析過程,根據域名獲得IP地址
三、可以緩存的儘可能緩存起來,減小網絡請求,減輕服務器負擔
網絡請求的安全性問題: 這塊瞭解的很少。我給你說說個人思路吧,利用對稱加密。服務器給咱們的數據能夠經過密鑰和其餘參數作個MD5加密,獲得一個key;在客戶端按照相同的辦法生成key而後與服務端給的作個對比。
對稱加密: 文件加密和解密使用相同的密鑰,即加密密鑰也能夠用做解密密鑰。DES、IDEA
非對稱加密: 非對稱加密算法須要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,若是用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;若是用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。RSA,RCC
16**、進程、線程通訊、Linux相關 **
如何開啓多進程?
一、經過在清單文件對四大組件指定android:process屬性。除此以外android是沒有辦法指定線程或者實體類運行所在的進程。
二、很是規方法:經過JNI在native層去fork一個新的進程。
多進程所帶來的問題: 一、靜態成員和單例模式徹底失效。
二、線程同步機制會徹底失效。
三、SharePreferences的可靠性會降低。 四、Application會屢次被建立,例如在推送或者即時通訊SDK中,須要單獨開一個進程來接收消息,那麼咱們在Application中初始化SDK的時候,須要判斷當前進程是否爲當前APP的主進程,是就初始化,不然不作任何操做。
進程間通訊方式對比:
方式
優勢
缺點
適用場景
Bundle
簡單易用
只支持Bundle支持的數據類型
四大組件之間的跨進程通訊
文件共享
簡單易用
不適合高併發場景,而且沒法作到即時通訊
無併發的情形,實時性不高的場景
AIDL
功能強大,支持一對多併發實時通訊
適用稍微複雜,須要處理線程同步問題
一對多通訊,實時性高
Messenger
功能通常,支持一對多串行實時通訊
不能很好處理高併發,只能傳輸Bundle支持的類型
低併發的一對多實時通訊,無需返回結果
ContentProvider
數據源訪問方面功能強大,支持一對多併發數據共享,能夠經過call方法進行擴展
能夠理解爲受約束的AIDL,主要是數據源提供CRUD操縱
一對多的進程間數據共享
Socket
功能強大,經過網絡傳輸字節流,支持一對多併發實時通訊
實現麻煩,不支持直接的RPC
網絡數據交換
**Linux****中的進程間通訊方式: **
一、命名管道 二、共享內存 三、信號量
**Android****中進程的級別: **
前臺進程(正在與用戶交互)、可見進程(有可見的界面)、服務進程、後臺進程、空進程
經常使用的Linux命令:mkdir 建立文件夾、rmdir 刪除文件夾、rm 刪除文件、mv 移動文件、cp 拷貝文件、cat 查看文件
tail 查看文件尾部、more 分頁查看文件、cd 切換當前目錄、ls 列出文件清單、reboot 重啓、date 顯示日期
cal 顯示日曆、ps 查看系統進程至關於windows 的任務管理器、ifconfig 配置網絡
** **
**Linux****進程和DVM的進程是否爲同一個概念? **
每個Android 應用程序都擁有一個獨立的虛擬機實例,應用程序都在它本身的進程中運行。而每個dvm都是在Linux中的一個進程,因此說能夠近似認爲是同一個概念。
獨立的進程能夠防止在虛擬機崩潰的時候全部程序都被關閉。
**Android****中的安全機制 **
一、Android 是基於Linux 內核的,所以Linux 對文件權限的控制一樣適用於Android。在Android 中每一個應用都有本身的/data/data/包名文件夾,該文件夾只能該應用訪問,而其餘應用則無權訪問。
二、Android 的權限機制保護了用戶的合法權益。如咱們的代碼想撥打電話、發送短信、訪問通訊錄、定位、訪問sdcard等全部可能侵犯用於權益的行爲都是必需要在AndroidManifest.xml 中進行聲明的,這樣就給了用戶一個知情權。而且在android6.0中引入了動態權限管理
三、Android 的代碼混淆以及apk的簽名保護了開發者的權益。
**AIDL****主要思路(步驟)就是: **
一、服務端建立一個Service來監聽客戶端的鏈接請求。建立AIDL文件,將接口暴露給客戶端,並在Service中實現這個接口。
二、客戶端綁定Service,並定成功以後將服務端返回的Binder對象轉換成AIDL中的接口類型,而後就能夠調用接口的方法,而且獲取返回值。
17**、Android新特性相關**
18、在技術上的發展有什麼規劃?(離職緣由)(實現本身的價值,學習牛逼的技術,公司的發展前景) **
以前的公司就是直接實現業務邏輯的,功能的話只要給時間必定能夠實現的。而後在上一家公司就是接觸到了一些思想層次上的,好比設計模式啊MVC之類的,而後買了一些書來看,如今在往這方面發展。之後的就要等我再學到必定層次再考慮了。
19、屏幕適配 **
1、**對應不一樣屏幕建立不一樣的dimen的文件夾,放置不一樣的大小 ,根據屏幕分辨率建立不一樣layout文件夾,使用權重來適配
2、**使用九切圖和SVG圖片、xml來代替直接使用png
3、長度單位用dp代替px ** 4**、使用wrap_content, match_parent, weight 5、**使用相對佈局,在開發中禁用絕對佈局
**上和左控制拉伸,下和右負責內容區域 五、使用線性佈局,放不下的時候用ScrollView包裹 **
20**、android分包、插件化、熱修復等相關知識: **
Dex分包 **
**引入緣由:**在apk代碼量愈來愈多的時候,每每會出現方法數量過多(超過了65536),而一個dex文件最多隻支持65536個方法;apk過大不能在一些舊版本的android手機上面安裝,由於android2.3之前的版本分配 用來執行dex優化的 內存只有5M。
android的加載器體系與java類加載器體系對比: **
一、PathClassLoader:加載安卓應用,只能加載
已安裝到系統中(即/data/app目錄下)的
apk文件。
二、 DexClass:能夠加載apk,jar,及dex文件。
加載一個類的時候,ClassLoader先遍歷一個裝在dex文件(每一個dex文件其實是一個DexFile對象)的數組(Element數組,Element是一個內部類),而後依次去加載所須要的class文件,直到找到爲止。
Dex注入的解決方案:假如咱們將第二個dex文件放入Element數組中,在加載第二個dex包中的類時,應該能夠直接找到。 **
Dex分包的注意要點: **
因爲第二個dex包是在Application的onCreate中動態注入的,若是dex包過大,會使app(Activity)的啓動速度變慢,所以,在dex分包過程當中必定要注意,第二個dex包不宜過大。
因爲上述第一點的限制,假如咱們的app愈來愈臃腫和龐大,每每會採起dex分包方案和插件化方案配合使用,將一些非核心獨立功能作成插件加載,核心功能再分包加載。
** **
**插件化 **
思路:經過在宿主app裏面註冊添加一些activity做爲插件app的容器,加載插件app,經過動態代理的方法去處理被
加載(被代理)的activity、fragment的生命週期。由此引出Activity與Fragment之間的傳值問題**
第三方服務:apkplug,尚未仔細研究就辭職了,由此引出久邦數碼舉辦的app創新設計大賽。
插件化第三方框架:360的DroidPlugin、攜程的DynamicAPK、今年初開源的Small
21**、android插件化是否有其餘更好的代替方法? **
**插件化引入: **
一、APK方法數量過多二、低版本手機安裝出錯
三、移動應用中的2/8定律,80%的用戶訪問20%的頁面,那麼剩下80%的頁面是不必用戶去下載的,只有在用到的時候去下載。經過這樣能夠大大減輕app對CPU、內存的負擔,同時也實現動態加載的目的。
**代替方案: **
一、移動應用從C/S架構向B/S架構的轉變。最近比較火的一個框架React Native。基於頁面級別的動態加載。二、買付費的Proguard
三、最笨的方法是刪除無用的代碼以及模塊
**熱修復 **
app上線以後須要緊急去修改一些有問題的代碼,常規的方法是從新測試、打包、混淆加密加固、上線。這樣太麻煩。
**第三方方案: **
**阿里巴巴的AndFix:**經過加載器讀取一個dex文件中的類,並找到被註解標記到的要修復的方法,再經過jni在C層替換掉本來出BUG的方法的指針,從而達到熱修復的目的。
QQ空間的熱修復方案:**MultiDex的思路,在應用啓動的時候,往Classloader的PathList裏面插入一個Dex,經過覆蓋掉出BUG的類來作到熱修復。QQ空間只出了理論方案,而這套方案的開源代碼實現,則是由 賈吉鑫 寫了一個 nuwa 託管在 Github 上。
** **
22**、怎麼定位 **
**anr****問題代碼位置? **
** **
ANR:**Application Not Response
致使ANR的緣由有:主線程(Activity、Service)是5 秒,BroadCastReceiver 是10 秒。(本身項目:在主線程去讀取SD卡)
**解決方案:**將全部耗時操做,好比訪問網絡,Socket 通訊,查詢大量SQL 語句,複雜邏輯計算等都放在子線程中去,而後經過handler.sendMessage、runonUITread去刷新UI;顯示Loading!!!;onReceive啓動Service
**定位:**發生ANR之後,系統會在/data/anr目錄下面生成一個traces.txt文件
第一步,先pull出/data/anr/traces.txt文件。 第二步,查看app被殺死時的線程id。 第三步,查看traces.txt裏關於該線程id的信息。
典型場景,調用關係比較複雜的時候,好比說主線程的方法裏面開了一個子線程,子線程得到了同步鎖,主線程的方法被阻塞掉。此時應該先分析主線程,查看什麼鎖被什麼線程hold住了,而後再對應去看那個線程。
23**、避免OOM的一些常見方法:**
一、App資源中儘可能少用大圖。使用Bitmap的時候要注意等比例縮小圖片,而且注意Bitmap的回收。 BitmapFactory.Options options = new BitmapFactory.Option(); options.inSampleSize = 2; //Options 只保存圖片尺寸大小,不保存圖片到內存 BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 2; Bitmap bmp = null; bmp = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts); //回收 bmp.recycle(); 二、結合組件的生命週期,釋放資源 三、IO流,數據庫查詢的遊標等應該在使用完以後及時關閉。 四、ListView中應該使用ViewHolder模式緩存ConverView 五、頁面切換的時候儘可能去傳遞(複用)一些對象,經過Intent傳遞過去
24**、Android中如何捕獲未捕獲的異常 **
一、自定義Application,實現Thread.UncaughtExceptionHandler
二、實現uncaughtException(Thread t, Throwable e)方法,在方法中處理異常。若是不能處理的話,通常android.os.Process.killProcess(android.os.Process.myPid());來結束本身,避免把異常信息報給用戶。
三、在Application初始化的時候設置Thread.setDefaultUncaughtExceptionHandler(this);
** **
25**、Android6.0新增的動態權限 **
一、對於6.0如下的權限及在安裝的時候,根據權限聲明產生一個權限列表,用戶只有在贊成以後才能完成app的安裝,也就是說權限在安裝的時候已經授予了。
二、對於6.0或以上的版本,谷歌把權限分爲了兩類,
一種是Normal Permission,例如訪問網絡、網絡狀態獲取、震動等;
另一種是Dangerous Permission,例如發送、讀取短信、打電話、讀取通訊錄、錄音等。而且引入了權限組的概念,若是你申請某個危險的權限,假設你的app早已被用戶受權了同一組的某個危險權限,那麼系統會當即受權,而不須要用戶去點擊受權
**權限申請方式: **
一、在清單文件裏面配置權限,跟之前同樣。
二、檢查權限ContextCompat.checkSelfPermission,方法返回值爲PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。
三、在Activity中使用ActivityCompat的requestPermissions,或者在Fragment裏面直接使用Fragment提供的requestPermissions方法去申請某一個危險權限,而後在onRequestPermissionsResult回調裏面進行業務邏輯。
**最簡單的解決方式:在gradle配置文件中把targetSDK改成小於23。 **
26**、佈局優化 **
一、使用includea標籤去複用相同的佈局
二、使用merge標籤去除同類的視圖
三、使用ViewStub來延遲加載一些不經常使用的佈局
27**、內存優化 **
一、珍惜Service資源,儘可能使用IntentService IntentService在內部實際上是經過線程以及Handler實現的,當有新的Intent到來的時候,會建立線程而且處理這個Intent,處理完畢之後就自動銷燬自身。所以使用IntentService可以節省系統資源。
二、實現一些在內存緊張的時候會回調的一些方法,好比Activity中的onLowMemory、onTrimMemory。好比中止動畫特效等。
三、經過Manifest中對Application配置更大的內存,可是通常不推薦。 android:largeHeap="true" 四、避免Bitmap的浪費,應該儘可能去適配屏幕設備。儘可能使用成熟的圖片加載框架,Picasso,Fresco,Glide等。 五、使用優化的容器,SparseArray等 六、其餘建議:儘可能少用枚舉變量,儘可能少用抽象,儘可能少增長類,避免使用依賴注入框架,謹慎使用library,使用代碼混淆,時當場合考慮使用多進程等。 七、避免內存泄漏(原本應該被回收的對象沒有被回收)。一旦APP的內存短期內快速增加或者GC很是頻繁的時候,就應該考慮是不是內存泄漏致使的。
28**、性能優化 **
一、防止過分繪製,經過打開手機的「顯示過分繪製區域」便可查看過分繪製的狀況。 二、最小化渲染時間,使用視圖樹查看節點,對節點進行性能分析。 3經過TraceView進行數據的採集以及分析。在有大概定位的時候,使用Android官方提供的Debug類進行採集。最後經過DDMS便可打開這個.trace文件,分析函數的調用狀況(包括在指定狀況下執行時間,調用次數) //開啓數據採集 Debug.startMethodTracing("test.trace"); //關閉 Debug.stopMethodTracing();
29**、SharedPreference **
SharedPreference.Editor的apply和commit方法異同: ** 1. apply沒有返回值而commit返回boolean代表修改是否提交成功 2. apply是將修改數據原子提交到內存, 然後異步真正提交到硬件磁盤, 而commit是同步的提交到硬件磁盤,所以,在多個併發的提交commit的時候,他們會等待正在處理的commit保存到磁盤後在操做,從而下降了效率。而apply只是原子的提交到內存,後面有調用apply的函數的將會直接覆蓋前面的內存數據,這樣從必定程度上提升了不少效率。 3. apply方法不會提示任何失敗的提示。
**注意點: **
0、每次調用commit()、apply()都會將整個settings所有寫到文件中,即便你只改動了一個setting。由於它是基於全局的,而不是增量的,因此你的客戶端代碼中必定不要出現一個putXXX就緊跟着一個commit/apply,而是put完全部你要的改動,最後調用一次commit/apply。 一、因爲在一個進程中,SharedPreference是單實例,通常不會出現併發衝突,若是對提交的結果不關心的話,建議使用apply。二、固然須要確保提交成功且有後續操做的話,仍是須要用commit(利用返回值)的。
三、**源碼中多線程同步問題:**SharedPreference經過一個標誌來控制多線程併發讀寫的,數據提交的時候,會把標誌加一,數據提交完畢的時候會減一,所以若是判斷到標誌大於0的話就證實還有數據沒有提交完成,那麼就把數據集(Map)從新拷貝一份再進行後續提交操做。
四、**多進程中:**SharePreferences的可靠性會降低。
SharedPreference的xml文件何時加載到內存中? **
app啓動Context初始化的時候,經過SharedPreferencesImpl的startLoadFromDisk中會起一個線程調用loadFromDiskLocked從磁盤上加載數據。
若是一個應用中有好幾個sharedPreferences時,每一個sp對應的SharedPreferencesImpl都會各自起一個線程去把xml中的數據加載到map中,後面全部的getXXX方法實際上都是從內存中取數據,不會再有讀磁盤的動做了。
**注意:**SharedPreference的序列化和解析的操做都是在內存中完成,因爲每個DVM分配的堆內存通常最大隻有16M,所以不建議在SharedPreference中保存太大的數據。
30**、Activity與Fragment傳值問題 **
一、findFragmentByTag或者getActivity得到對方的引用(強轉)以後,再相互調用對方的public方法,耦合度高。
二、經過Bundle的方法進行傳值,fragment.setArguments()
三、經過EventBus或者RxBus,耦合度低。
31**、Activity相關 **
Activity生命週期 **
Activity 從建立到銷燬有多種狀態,從一種狀態到另外一種狀態時會激發相應的回調方法,這些回調方法包括:
onCreate onStart onResume onPause onStop onDestroy
其實這些方法都是兩兩對應的,onCreate 建立與onDestroy 銷燬;onStart 可見與onStop 不可見;onResume 可編輯(即焦點)與onPause;在Activity 被onStop 後,可是沒有被onDestroy,在再次啓動此Activity 時就調用onRestart(而再也不調用onCreate)方法;若是被onDestroy 了,則是調用onCreate 方法。
** **
Activity的啓動原理(大概把過程說出來) **
1.不管是經過Launcher來啓動Activity,仍是經過Activity內部調用startActivity接口來啓動新的Activity,都經過Binder進程間通訊進入到ActivityManagerService進程中,而且調用ActivityManagerService.startActivity接口;
2.ActivityManagerService調用ActivityStack.startActivityMayWait來作準備要啓動的Activity的相關信息;
3.ActivityStack通知ApplicationThread要進行Activity啓動調度了,這裏的ApplicationThread表明的是調用ActivityManagerService.startActivity接口的進程,對於經過點擊應用程序圖標的情景來講,這個進程就是Launcher了,而對於經過在Activity內部調用startActivity的情景來講,這個進程就是這個Activity所在的進程了;
4.ApplicationThread不執行真正的啓動操做,它經過調用.activityPaused接口進入到ActivityManagerService進程中,看看是否須要建立新的進程來啓動Activity;
5.對於經過點擊應用程序圖標來啓動Activity的情景來講,ActivityManagerService在這一步中,會調用startProcessLocked來建立一個新的進程,而對於經過在Activity內部調用startActivity來啓動新的Activity來講,這一步是不須要執行的,由於新的Activity就在原來的Activity所在的進程中進行啓動;
6.ActivityManagerServic調用ApplicationThread.scheduleLaunchActivity接口,通知相應的進程執行啓動Activity的操做;
7.ApplicationThread把這個啓動Activity的操做轉發給ActivityThread,ActivityThread經過ClassLoader導入相應的Activity類,而後把它啓動起來。
**兩個Activity 之間跳轉時必然會執行的是哪幾個方法? **
通常狀況下好比說有兩個activity,分別叫A,B,當在A 裏面激活B 組件的時候, A 會調用onPause()方法,而後B 調用onCreate() ,onStart(), onResume()。
這個時候B 覆蓋了窗體, A 會調用onStop()方法. 若是B 是個透明的,或者是對話框的樣式, 就不會調用A 的onStop()方法。
**異常狀態下的Activity生命週期 **
資源相關的系統配置發生改變或者資源不足:例如屏幕旋轉,當前Activity會銷燬,而且在onStop以前回調onSaveInstanceState保存數據,在從新建立Activity的時候在onStart以後回調onRestoreInstanceState。其中Bundle數據會傳到onCreate(不必定有數據)和onRestoreInstanceState(必定有數據)。 防止屏幕旋轉的時候重建,在清單文件中添加配置: android:configChanges="orientation"。屏幕旋轉的時候會回調onConfigurationChanged方法。
Activity的啓動模式** 一、standard:每次激活Activity時(startActivity),都建立Activity實例,並放入任務棧; 二、singleTop:若是某個Activity本身激活本身,即任務棧棧頂就是該Activity,則不須要建立,其他狀況都要建立Activity實例; 三、singleTask:若是要激活的那個Activity在任務棧中存在該實例,則不須要建立,只須要把此Activity放入棧頂,即把該Activity以上的Activity實例都pop,並調用其onNewIntent;可是getIntent方法返回的仍是舊的Intent。 四、singleInstance:啓用新的任務棧建立Activity實例,若是應用2也要激活Activity,則不須要建立,兩應用共享該Activity實例。
32**、Service相關,Service與Activity之間的交互-利用進程間通訊的方式 **
Service運行所在的進程**:不配置的狀況下默認在當前app進程中的主線程中運行,所以不能執行耗時操做。
Service的兩種啓動方式 **
Activity 經過bindService(Intent service, ServiceConnection conn, int flags)跟Service 進行綁定,當綁定成功的時候Service 會將代理對象經過回調的形式傳給conn,這樣咱們就拿到了Service 提供的服務代理對象。在Activity 中能夠經過startService 和bindService 方法啓動Service。通常狀況下若是想獲取Service 的服務對象那麼確定須要經過bindService()方法,好比音樂播放器,第三方支付等。若是僅僅只是爲了開啓一個後臺任務那麼能夠使用startService()方法。
**非綁定模式:**當第一次調用startService 的時候執行的方法依次爲onCreate()、onStartCommand(),(onStart())。當Service 關閉的時候調用onDestory 方法。
**綁定模式:**第一次bindService()的時候,執行的方法爲onCreate()、onBind()解除綁定的時候會執行onUnbind()、onDestory()。
**注意 **
一、Service 實例只會有一個,也就是說若是當前要啓動的Service 已經存在了那麼就不會再次建立該Service 固然也不會調用onCreate()方法。
二、一個Service 能夠被多個客戶進行綁定,只有全部的綁定對象都執行了onBind()方法後該Service 纔會銷燬,不過若是在混合模式下,有一個客戶執行了onStart()方法,那麼這個時候若是全部的bind 客戶都執行了unBind()該Service 也不會銷燬。
**IntentService **
Service 自己存在兩個問題:
一、Service 不會專門啓動一條單獨的進程,Service 與它所在應用位於同一個進程中;
二、Service 也不是專門一條新線程,所以不該該在Service 中直接處理耗時的任務;
IntentService的優勢: **
會建立獨立的worker 線程來處理全部的Intent 請求;
會建立獨立的worker 線程來處理onHandleIntent()方法實現的代碼,無需處理多線程問題;
全部請求處理完成後,IntentService 會自動中止,無需調用stopSelf()方法中止Service;
爲Service 的onBind()提供默認實現,返回null;
爲Service 的onStartCommand 提供默認實現,將請求Intent 添加到隊列中;
IntentService的原理: **
IntentService在內部實際上是經過線程以及Handler實現的,當有新的Intent到來的時候,會在onCreate中建立線程,Looper以及Handler。在onStart中經過Handler通知子線程去回調onHandleIntent方法去處理這個Intent,處理完畢之後就經過stopSelf方法銷燬自身。所以使用IntentService可以節省系統資源。
**如何讓Service成爲前置進程? **
在onStartCommand中發一個Notification通知。
**Service **的onStartCommand 方法有幾種返回值?各表明什麼意思? **
有四種返回值,不一樣值表明的意思以下:
一、START_STICKY:若是service進程被kill掉,保留service 的狀態爲開始狀態,但不保留遞送的intent對象。隨後系統會嘗試從新建立service,因爲服務狀態爲開始狀態,因此建立服務後必定會調用onStartCommand方法。若是在此期間沒有任何啓動命令被傳遞到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 的狀況下會執行,不然不執行。
33**、廣播 **
**內部通訊實現機制:**經過Android 系統的Binder 機制實現通訊。
**廣播的兩種分類: **
無序廣播:徹底異步,邏輯上能夠被任何廣播接收者接收到。優勢是效率較高。缺點是一個接收者不能將處理結
果傳遞給下一個接收者,並沒有法終止廣播intent 的傳播。(優先級對無序廣播也會生效)
有序廣播:按照被接收者的優先級順序,在被接收者中依次傳播。每一個接收者有權終止廣播,可是若是設置了最終接收者除外。若是傳播過程當中沒有廣播被終止,最終接收者會回調兩次onReceive,第一次是按照正常順序觸發的,第二次是最終接受觸發。
**判斷廣播類型:**在onReceive方法中經過isOrderedBroadcast()方法
**註冊:**廣播接收者能夠在清單文件中設置,也能夠在代碼中設置,可是要注意註銷,不然會引起內存泄漏。
**動態註冊的優先級是經過註冊前後來肯定的,先註冊的接收者優先級高。 **
**廣播的生命週期 **
BroadCastReceiver 的生命週期
一、廣播接收者的生命週期很是短暫的,在接收到廣播的時候建立,onReceive()方法結束以後銷燬;
二、廣播接收者中不要作一些耗時的工做,不然會彈出Application No Response 錯誤對話框;(不能超過10秒)
三、最好也不要在廣播接收者中建立子線程作耗時的工做,由於廣播接收者被銷燬後進程就成爲了空進程,很容易
被系統殺掉;最好新開一個Service**來實現;
**如何讓廣播在指定app中才能接收?即廣播自定義權限 **
一、在清單文件中經過permission標籤訂義自定義權限,而後uses-permission聲明這個權限
二、在指定app中也一樣作以上操做,定義廣播接收者時候也要添加permission屬性。
34**、ContentProvider相關 **
**簡要介紹ContentProvider如何實現了應用程序之間的數據共享? **
一、APP若是須要把數據共享出去,先要自定義ContentProvider,實現CURD方法,在清單文件中註冊。
二、第三方APP就能夠經過ContentResolver進行數據的操做。
三、用戶能夠經過註冊ContentObserver對數據提供者的數據變化進行監聽,例如監聽短信數據庫來實現短信驗證碼自動填寫。
35**、SurfaceView與View的區別 **
區別:surfaceView是在一個新起的單獨線程中能夠從新繪製畫面,而View必須在UI的主線程中更新畫面。那麼在UI的主線程中更新畫面 可能會引起問題,好比你更新畫面的時間過長,那麼你的主UI線程會被你正在畫的函數阻塞。那麼將沒法響應按鍵,觸屏等消息。當使用surfaceView 因爲是在新的線程中更新畫面因此不會阻塞你的UI主線程。但這也帶來了另一個問題,就是事件同步。好比你觸屏了一下,你須要surfaceView中 thread處理,通常就須要有一個event queue的設計來保存touch event,這會稍稍複雜一點,由於涉及到線程同步。
**因此基於以上,根據遊戲特色,通常分紅兩類。 **
1 被動更新畫面的。好比棋類,這種用view就行了。由於畫面的更新是依賴於onTouch 來更新,能夠直接使用 invalidate。 由於這種狀況下,這一次Touch和下一次的Touch須要的時間比較長些,不會產生影響。
2 主動更新。好比一我的在一直跑動。這就須要一個單獨的thread不停的重繪人的狀態,避免阻塞main UI thread。因此顯然view不合適,須要surfaceView來控制。
Scroller的原理
public classMyView extendsView {
private Context mContex
Scroller mScroller =****newScroller**(mContext);**
private void smoothScrollTo**(intdestX,intdestY)****{**
int scrollX = getScrollX**();**
//計算滑動距離,startScroll保存參數
int delta = destX - scrollX**;**
mScroller**.startScroll(scrollX,0,destX,0);**
}
@Override
public void computeScroll**()****{**
if **(mScroller.computeScrollOffset())****{// **
//滑動而且刷新
scrollTo**(mScroller.getCurrX(),mScroller.getCurrY());**
postInvalidate**();**
}
}
}** **
** **
**Scroller****執行流程裏面的三個核心方法以及滑動的原理: **
mScroller.startScroll()
mScroller.computeScrollOffset()
view.computeScroll()
一、在mScroller.startScroll()中爲滑動作了一些初始化準備。
好比:起始座標,滑動的距離和方向以及持續時間(有默認值),動畫開始時間等
二、mScroller.computeScrollOffset()方法主要是根據當前已經消逝的時間來計算當前的座標點。
由於在mScroller.startScroll()中設置了動畫時間,那麼在computeScrollOffset()方法中依據已經消逝的時間就很容易獲得當前時刻應該所處的位置並將其保存在變量mCurrX和mCurrY中。除此以外該方法還可判斷動畫是否已經結束。
三、postInvalidate方法會致使View的重繪,重繪的時候又會回調computeScroll方法去進行View的滑動,如此往復。
36**、工具相關 **
**請介紹下adb、ddms、aapt 的做用 **
**adb **Android Debug Bridge ,Android調試橋的意思。一個命令行工具,Android的主要調試工具。
ddms Dalvik Debug Monitor Service,dalvik 調試監視服務。ddms 是一個在adb 基礎上的一個圖形化工具。ddms是程序執行的查看器,能夠查線程和堆棧信息。而traceView是ddms中的一部分,用於程序性能分析。
aapt 即Android Asset Packaging Tool,在SDK 的build-tools 目錄下。該工具能夠查看,建立,更新ZIP格式的文檔附件(zip, jar, apk)。也可將資源文件編譯成二進制文件,儘管咱們沒有直接使用過該工具,可是開發工具會使用這個工具打包apk 文件構成一個Android 應用程序。
37**、ListView等列表控件 **
**優化問題: **
一、使用ViewHolder模式,建立靜態ViewHolder類,複用ConverView 二、使用分頁加載 三、使用弱引用去引用一些控件。由於控件上有Context對象,這樣作防止了內存泄漏。
**ViewHolder ****爲何要聲明爲靜態類? **
非靜態內部類擁有外部類對象的強引用,所以爲了不對外部類(外部類極可能是Activity)對象的引用,那麼最
好將內部類聲明爲static 的。
使用Handler的時候:自定義的Handler內部類應該聲明爲static,而且使用弱引用去引用Context等,防止Context不能正常銷燬而致使內存泄漏。
ListView****中的設計模式**:adapter模式、觀察者模式、享元模式(ItemView的複用)
ScrollView****中嵌套ListView問題: **
問題:**例如在滑動頁面中嵌套一個顯示物流信息的ListView,這樣會致使ListView顯示不全,只顯示一個條目。
解決辦法:在ScrollView裏面加一層LinearLayout,經過代碼動態設置ListView的高度。
38****、視屏播放 **
一、MediaPlayer 二、VideoView(內部仍是使用了MediaPlayer) 三、第三方開源萬能播放器VitamioPlayer
39****、Intent **
Intent ****傳遞數據時,能夠傳遞哪些類型數據? **
Intent 能夠傳遞的數據類型很是的豐富,java 的基本數據類型和String 以及他們的數組形式均可以,除此之
外還能夠傳遞實現了Serializable 和Parcelable 接口的對象。
Serializable ****(Java)和Parcelable (Android)的區別 **
1.在使用內存的時候,Parcelable 類比Serializable 性能高,因此推薦使用Parcelable 類。
2.Serializable 在序列化的時候會產生大量的臨時變量,從而引發頻繁的GC。
3.Parcelable 不能使用在要將數據存儲在磁盤上的狀況。儘管Serializable 效率低點,但在這種狀況下,仍是建議用Serializable 。
實現:
1 Serializable 的實現,只須要繼承Serializable ,指定序列化ID便可。這只是給對象打了一個標記,系統會自動將其序列化。
2 Parcelabel 的實現,須要在類中添加一個靜態成員變量CREATOR,這個變量須要繼承Parcelable.Creator 接口。
40****、Fragment相關**
FragmentManager****的add方法與replace方法的異同: **
一、add 的時候是把全部的Fragment 一層一層的疊加到了FrameLayout 上
二、replace 的話首先將該容器中的其餘Fragment 去除掉而後將當前Fragment 添加到容器中,所以使用replace方法的時候要注意會觸發onDestroyView。**
三、通常思路是先add進來,而後經過hide以及show來進行Fragment的切換,此時Fragment的生命週期沒有變化**。
Fragment****實現Activity壓棧和出棧的效果**:經過addToBackStack方法實現,內部維護了一個雙向鏈表。
Activity和Fragment之間你是怎麼傳值的? **
41****、Android中的動畫 **
動畫分類:幀動畫,補間動畫,屬性動畫(實際View的移動,點擊事件會跟隨)
如何爲Activity或者Fragment添加動畫? **
一、自定義主題,複寫相應的屬性,以下圖所示 二、在finish或者startActivity以後調用overridePendingTransition
42****、簽名、多渠道打包,上線流程 **
簽名簡介:**在Android 系統中,全部安裝到系統的應用程序都必有一個數字證書,此數字證書用於標識應用程序的做者和在 **
應用程序之間創建信任關係。Android 系統要求每個安裝進系統的應用程序都是通過數字證書籤名的。
簽名好處:**(1)有利於程序升級,當新版程序和舊版程序的數字證書相同時,Android 系統纔會認爲這兩個程序是同一個程序
的不一樣版本。若是新版程序和舊版程序的數字證書不相同,則Android 系統認爲他們是不一樣的程序,併產生衝突,會
要求新程序更改包名。
(2)有利於程序的模塊化設計和開發。Android 系統容許擁有同一個數字簽名的程序運行在一個進程中,Android程序會將他們視爲同一個程序。因此開發者能夠將本身的程序分模塊開發,而用戶只須要在須要的時候下載適當的模塊。
在簽名時,須要考慮數字證書的有效期: **
(1)數字證書的有效期要包含程序的預計生命週期,一旦數字證書失效,持有改數字證書的程序將不能正常升級。
(2)若是多個程序使用同一個數字證書,則該數字證書的有效期要包含全部程序的預計生命週期。
(3)Android Market 強制要求全部應用程序數字證書的有效期要持續到2033 年10 月22 日之後。