回顧一下基礎的細節

博客轉移到個人站點:http://www.wangchengmeng.club/2018/02/01/%E5%9B%9E%E9%A1%BE%E4%B8%80%E4%B8%8B%E5%9F%BA%E7%A1%80%E7%9A%84%E7%BB%86%E8%8A%82/

歡迎來吐槽

也許在逐漸的工作中,個人的技術知識在不斷的成長,但往往會忽略掉一些基礎細節知識,偶爾回顧一下,其實基礎反而會更加突出一個人的學習。

layout_weight怎麼理解?

    layout_weight的尺寸分配一般是先滿足設置尺寸的分配然後剩下的尺寸在進行比例分配的。如果一個view需要設置1:2的比例顯示,可以在LinearLayout中設置weightSum進行設置總的比例,然後在設置子View的比例。

LinerLayout:按照基準線對其中有個weightSum表示這個佈局總分成多少分,比如2份,即使只有一個子控件weight=1,也只會佔一半
weight:是按照比例劃分的,先安排好固定大小的值,剩下的按照weight的比例分配
如果含有weight的每個空間都是match_parent,那就按照相反的比例去分配,

layout_gravity和gravity的區別?

首先:所有layout_開頭的屬性都是交給父容器去設置的。

layout_gravity是根據父佈局設置位置的,而gravity是根據自身內容設置位置。

Handler機制是什麼?

Handler是Android官方給我們提供的一套更新UI線程的機制,也是一套消息處理機制,可以通過Handler來處理消息,更新UI等。

然後Handler機制大約是這樣的:首先Handler發送一個消息MessageQueue裏面,然後通過Looper的loop方法進行無限循環,如果產生了一個新消息,那麼就調用handler的handlermessage方法進行餘下的操作。之所以這樣做的原因是因爲避免多線程併發更新UI線程所產生的問題的,如果我們允許其他子線程都可以更新界面,那麼勢必會造成界面的錯亂(因爲沒有加鎖機制),如果我們加鎖,又會影響速度,所以,只能在主線程即UI線程裏面更新界面。

只能在UI線程裏面更新界面嗎?

只能在主線程中更新UI,我相信是很多開發者信口拈來的一句話,但真的是這樣?爲什麼要這樣呢?

其實在子線程中也可以更新UI,翻翻ViewRootImp的源碼就知道,之所以子線程不能更新界面,是因爲Android在線程的方法裏面採用checkThread進行判斷是否是主線程,而這個方法是在ViewRootImpl中的,這個類是在onResume裏面才生成的,因此,如果這個時候子線程在onCreate方法裏面生成更新UI,而且沒有做阻塞,就是耗時多的操作,還是可以更新UI的。

Android子線程更新UI的方式有幾種?

一般情況下,我們都採用Handler的方式進行更新UI,當然,代碼層的實現有不同的方法,比如可以使用Handler的post方法進行更新UI,或者用Handler的sendMessage方法進行更新UI,或者通過View的post方法進行更新,還有一個是runOnUIThread也是可以進行更新的。但這些本質上還是通過Handler進行子線程的更新。

當然,現在這種異步操作方式很多,AyncTsk、Rxjava等都屏蔽了內部消息機制的通信和處理,異步操作起來更加方便,特別是Rxjava這種響應式,異步處理更加方便。

使用Handler的時候一般會遇到什麼問題?

比如說子線程更新UI,是因爲觸發了checkThread方法檢查是否在主線程更新UI,還有就是子線程中沒有Looper,這個原因是因爲Handler的機制引起的,因爲Handler發送Message的時候,需要將Message放到MessageQueue裏面,而這個時候如果沒有Looper的話,就無法循環輸出MessageQueue了,這個時候就會報Looper爲空的錯誤。可以在子線程中主動調用   Looper.myLooper()該方法,那樣在子線程中就可以獲取到輪訓器了。詳情可以仔細看一下[Handler源碼分析](http://blog.csdn.net/xiaohuanqi/article/details/48899985)

HandlerThread是什麼?

HandlerThread是Android官方給我們提供好的一套子線程的Handler,也就是異步處理機制,它是爲了避免線程切換導致空指針異常的錯誤。

怎麼在主線程中通知子線程?這樣做有什麼好處?

可以利用HandlerThread進行生成一個子線程的Handler,並且實現handlerMessage方法,然後在主線程裏面也生成一個Handler,然後通過調用sendMessage方法進行通知子線程。同樣,子線程裏面也可以調用sendMessage方法進行通知主線程。這樣做的好處比如有些圖片的加載啊,網絡的訪問啊可能會比較耗時,所以放到子線程裏面做是比較合適的。

Android中有幾種佈局?

Android中一般有五種佈局,首先比較常用的兩種佈局是LinearLayout和RelativeLayout,就是線性佈局和相對佈局,線性佈局的話一般是指定方向,然後從左往右或者從上往下排列的,相對佈局的話是依賴與父控件或者其他View進行確定位置的。然後還有FrameLayout,TableLayout和AbsoluteLayout,其中FrameLayout就是一層一層的疊加的,TableLayout有點類似與HTML的表格,然後AbsoluteLayout的話是通過座標確定位置的,因爲Android屏幕多種多樣,所以一般都不推薦用絕對佈局。

說下Activity的生命週期

Activity的生命週期是這樣的,首先當用戶啓動一個Activity的時候,就會調用onCreate的方法,這個時候一般把要初始化的東西都放到這裏,接着就會調用onStart方法,這個時候如果需要監聽UI的變化或者數據的變化,一般可以放到這裏,然後執行onResume方法,這個時候界面就已經顯示好了。然後如果這個時候按了home鍵的話,就會調用onPause方法,接着是執行onStop方法,這個時候可以取消或停止剛纔監聽的UI或數據變化的監聽器,接着如果這個時候你返回到剛纔的Activity的話,可能產生兩種情況,一種就是因爲系統回收了你的Activity,這個時候就重新執行onCreate onStart onResume,如果系統沒有回收你的Activity的話,就執行onRestart onResume方法,如果這個時候又不想回去,剛好內存不夠了,就會執行onDestory方法進行銷燬。

Activity的啓動模式有幾種?

有四種啓動模式,首先默認的啓動模式是standard,就是沒創建一個Activity就會將其壓入任務棧棧頂,不管是否存在,一種是singleTop,就是如果任務棧棧頂剛好是要顯示的Activity,它就不會創建一個新的Activity,並調用onNewIntent()方法,如果不是,就會重新創建一個新的Activity,一種是singleTask,如果Activiy 已經存在,不管是棧頂還是棧中,它就會移除該 Activity上面所有的任務使該Activity位於棧頂,並調用onNewIntent()方法。一種是singleInstance,使該啓動模式的Acitivity位於一個單獨開啓的棧中。

Activity的緩存方法是怎麼樣的?

可以在onSaveInstanceState中將要保存的數據保存起來,可以通過Bundle進行臨時保存,然後在onCreate中的Bundle中取出來進行恢復,這樣就可以避免Activity被銷燬的時候數據的清空。因爲onSaveInstanceState在Activity銷燬之前必然會調用,所以可以在這裏做緩存操作。記住,這個是系統未經你同意的時候就銷燬的時候纔會的。

Fragment的生命週期是怎麼樣的,跟Activity有什麼關係?

Fragment是Activity的一個組件片段,也就是說他的生命週期是依賴於Activity的,但是它比Activity多了幾個生命步驟,首先onAttach當fragment加入Activity的時候調用,然後是onCreate進行啓動Activity,接着是onCreateView進行繪製View,一般的View就是這裏繪製的,然後是onActivityCreated,接着跟Activity的生命週期差不多,調用onStart和onResume,然後是onPause,onStop,如果這個時候需要回收Fragment的時候,就會調用,接着是onDestoryView銷燬佈局,然後是onDestory和onDetach完成。

爲什麼在Service中創建子線程而不是Activity中?

因爲假如在Activity中創建子線程的話,當Activity銷燬的時候,這個時候重新再調用該Activity就會重新走新的生命週期,這個時候就無法再重新獲取到剛纔的子線程,而且如果在一個Activity中創建子線程,另一個Activity也無法操作該子線程,但是Service就不一樣,所有的Activity都可以和Service關聯,即使是Activity被銷燬了,只要再重新建立聯繫就好了,所以,一般後臺任務都是通過Service去控制的。此外,如果在Activity中創建的子線程當Activity銷燬的時候子線程任務還沒完成,那麼會出現內存泄漏。

Intent可以傳遞哪些數據?怎麼傳遞?

Intent可以傳遞String類型的,基本類型,還有對象,如果是基本類型,可以通過Intent的方法直接傳遞就好了,如果是對象的話,一般可以通過Bundle進行傳遞,有些對象需要進行序列化和包裹化。

怎麼啓動Service?

有兩種啓動方式:一種是通過startService進行啓動,這個時候Service跟啓動的Activity沒有關聯,只有當調用stopService的時候纔會結束Service,他的生命週期是:onCreate->onStartCommand->Service Run ->stopService->onDestory();

如果是通過bindService啓動的,那麼這個Service就跟啓動他的進程有關了,這個時候如果啓動他的進程銷燬了,那麼這個Service也緊跟着銷燬了或者直接調用unBindService,生命週期是:onCreate->onBindService->Service Run->unBindService->onDestory.

廣播的動態註冊和靜態註冊有什麼區別?

靜態註冊:在AndroidManifest.xml文件中進行註冊,當App退出後,Receiver仍然可以接收到廣播並且進行相應的處理

動態註冊:在代碼中動態註冊,當App退出後,也就沒辦法再接受廣播了。

URI的格式和意義。

URI叫做統一資源標識符,主要分四部分,第一部分是協議名稱,可以是官方的,也可以自定義,第二部分是是URI的授權部分,是唯一標識符,用來定位ContentProvider。格式一般是自定義ContentProvider類的完全限定名稱,註冊時需要用到,如:com.alexzhou.provider.NoteProvider第三部分部分和第四部分部分:是每個ContentProvider內部的路徑部分,C和D部分稱爲路徑片段,C部分指向一個對象集合,一般用表的名字,如:/notes表示一個筆記集合;D部分指向特定的記錄,如:/notes/1表示id爲1的筆記,如果沒有指定D部分,則返回全部記錄。

Android存儲形式有幾種?

1.SQLite方式,SQLite是一個輕量級的數據庫, 支持基礎的SQL語法,官方提供了一個SQLiteDatabase的類,並提供一些api。
2.SharedPreference:存儲簡單的參數信息,本質上是xml.
3.File:文件存儲,常用來存儲大數據量的數據,但是更新麻煩。
4.ContentProvide,一般情況下數據在各個應用中是私密的,但是因爲它也是可以用來存儲分享數據。
5.網絡存儲,將數據放到網絡雲裏面,然後通過網絡進行訪問。

如何判斷應用被強制殺死?以及如何解決應用被強制殺死?

可以在Application中定義一個static常量,賦值爲-1,然後在歡迎頁面修改值爲0,如果被強殺,Application被重新初始化,這個時候如果父Activity判斷該常量是多少。

如果在每一個Activity的onCreate裏判斷是否被強殺,冗餘了,封裝到Activity的父類中,如果被強殺,跳轉回主界面,如果沒有被強殺,執行Activity的初始化操作,給主界面傳遞intent參數,主界面會調用onNewIntent方法,在onNewIntent跳轉到歡迎頁面,重新來一遍流程。

Json有什麼優勢?

JSON格式簡單,兼容性高,易於讀寫,並且傳輸的帶寬小,方便解析,並且服務端容易生成。

動畫有哪些類型,動畫的區別?

 在Android3.0以前,動畫有兩種類型,一種是補間動畫,即tween,他指的是通過自身的變形達到的效果,比如說透明度的變化,放大縮小等,還有一種是幀動畫,即Frame,是通過一針一針的對圖片進行連貫起來播放的,Android3.0的時候定義了一個屬性動畫,即PropertyAnimation,指的是控件的真實移動,就是不斷的改變某些屬性的值進行的。具體可以通過實現ValueAnimator等類進行實現。

Asset和res目錄的區別?

Asset不會在R文件裏面生成一個ID,所以它不能直接用R文件來調用,這就說明要讀取Asset目錄下的文件需要指定文件的目錄,可以通過AssetManager類來訪問。res會自動在R文件裏面生成id,直接可以用R.的方式進行訪問資源。

Android怎麼優化啓動速度?

因爲Android啓動應用程序一般分爲兩種,一種是冷啓動,就是要啓動的應用程序沒有後臺進程的啓動,這個時候需要重新分配一個進程給他,所以這個時候會先初始化Application類,再創建和初始化MainAcitvity 類,最後顯示到界面上,還有一種是熱啓動,就是後臺還有該應用的進程,比如說按下的home鍵或者返回鍵,雖然表面上退出了,但是在任務棧裏面仍然還存在的,這個時候就不需要再初始化Application類了,只要重新初始化MainActivity了。因爲大多數應用的啓動都是冷啓動(用戶習慣將應用程序在任務棧中刪除),所以這個時候可以採取這幾個步驟,比如儘量不在Application的構造器,attachBaseContext方法和onCreaete方法中做過多的耗時操作,將一些數據預取放在異步線程中,可以採Callback的方式。優化MainActivity,儘量不要在MainActivity的onCreate,onStart和onResume等方法裏面做過多的耗時操作。

Android怎麼加快Activity的顯示速度?

首先因爲Activiy的顯示是在這幾個生命週期之間的,onCreate,onStart,和onResume,這個時候我們需要將我們需要初始化的數據分類,比如說我們將一些只需要初始化的一次的數據放到onCreate中,儘量不要在onCreate中做耗時的操作,然後將需要加載比較長時間的數據放到onResume中,可以利用handler的機制進行更新UI,或者放到AsyncTask逐個顯示,然後可以設置一些動畫進行顯示,如果這個時候有許多數據都是一次顯示的, 那麼可以在onCreate裏面進行標記,並且在onResume裏面判斷是否需要初始化,初始化完成以後就立刻false掉,這樣就可以避免多次初始化了,也可以提升Activity的顯示速度。

Android內存泄漏可以引發什麼問題?

可能使程序造成卡頓的現象,或者莫名的消失,因爲內存過大,系統就更可能的回收這一塊的內存,或者直接崩潰。

產生Android內存泄漏的原因有什麼?

handler等生命週期較長的匿名內部類,因爲這些匿名內部類可能會持有外部的引用,從而導致短期內就算Activity退出而一些資源沒有被回收,數據結構未優化,圖片沒有優化,沒有注意到對象的生命週期,造成許多對象沒有被回收,過多的使用Service,單例的過多使用,無效的資源等等。

怎麼處理Android內存泄漏?

可以使用更加輕量的數據結構,比如ArrayMap而不是HashMap,避免在Android裏面使用enum,減小Bitmap對象的內存佔用,可以採用縮放比例,或者使用緩存縮略圖的方式。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章