Android基礎知識

Activity生命周期。
  • 啟動Activity: onCreate()—>onStart()—>onResume(),Activity進入運行狀態。

  • Activity退居后臺: 當前Activity轉到新的Activity界面或按Home鍵回到主屏: onPause()—>onStop(),進入停滯狀態。

  • Activity返回前臺: onRestart()—>onStart()—>onResume(),再次回到運行狀態。

  • Activity退居后臺,且系統內存不足, 系統會殺死這個后臺狀態的Activity(此時這個Activity引用仍然處在任務棧中,只是這個時候引用指向的對象已經為null),若再次回到這個Activity,則會走onCreate()–>onStart()—>onResume()(將重新走一次Activity的初始化生命周期)

  • 鎖屏:onPause()->onStop()

  • 解鎖:onStart()->onResume()

Activity生命周期流程圖

通過Acitivty的xml標簽來改變任務棧的默認行為
  • singleTop : 棧頂復用模式。這種模式下,如果新Activity已經位于任務棧的棧頂,那么此Activity不會被重新創建,所以它的啟動三回調就不會執行,同時Activity的onNewIntent()方法會被回調。如果Activity已經存在但是不在棧頂,那么作用與standard模式一樣。
  • singleTask: 棧內復用模式。創建這樣的Activity的時候,系統會先確認它所需任務棧已經創建,否則先創建任務棧。然后放入Activity,如果棧中已經有一個Activity實例,那么這個Activity就會被調到棧頂。onNewIntent(),并且singleTask會清理在當前Activity上面的所有Activity(clear top)
  • singleInstance : 加強版的singleTask模式,這種模式的Activity只能單獨位于一個任務棧內,由于棧內復用的特性,后續請求均不會創建新的Activity,除非這個獨特的任務棧被系統銷毀了。

Activity的堆棧管理以ActivityRecord為單位,所有的ActivityRecord都放在一個List里面。可以認為一個ActivityRecord就是一個Activity棧


Activity緩存方法

onSaveInstanceState()回調方法,一定會在Activity被回收之前調用。方法中有一個Bundle參數,putString()、putInt()等方法需要傳入兩個參數,一個鍵一個值。數據保存之后會在onCreate中恢復,onCreate也有一個Bundle類型的參數。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //這里,當Acivity第一次被創建的時候為空
        //所以我們需要判斷一下
        if( savedInstanceState != null ){
            savedInstanceState.getString("anAnt");
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putString("anAnt","Android");

    }

  • onSavaInstanceState() 方法被調用的幾種情況
    1.當按下HOME鍵時:
    因為系統不知道你按下HOME鍵后要運行多少其他的程序,自然也不知道Activity是否會被銷毀,故系統會調用onSaveInstanceState(),讓用戶有機會保存某些非永久性的數據。
    2.按下多任務鍵,選擇運行其他程序時。
    3.按下電源鍵鎖屏時。
    4.從當前Activity中啟動一個新的Activity時。
    5.屏幕方向切換時:
    在屏幕切換之前系統會銷毀當前Activity,在屏幕切換之后系統又會自動地創建該Activity,所以該方法一定會被調用。

總而言之,onSaveInstanceState()的調用遵循的原則是:當系統“未經許可”銷毀了你的Activity時,就會被調用。因為系統必須提供一個讓你保存數據的機會。

  • 注意:
    1.布局中的每一個View默認實現了onSaveInstanceState()方法,這樣的話,這個UI的任何改變都會自動地存儲和在activity重新創建的時候自動地恢復。但是這種情況只有在你為這個UI提供了唯一的ID之后才起作用,如果沒有提供ID,app將不會存儲它的狀態。
    2.由于onSaveInstanceState()方法調用的不確定性,你應該只使用這個方法去記錄activity的瞬間狀態(UI的狀態)。不應該用這個方法去存儲持久化數據。當用戶離開這個activity的時候應該在onPause()方法中存儲持久化數據(例如應該被存儲到數據庫中的數據)。
    3.onSaveInstanceState()如果被調用,這個方法會在onStop()前被觸發,但系統并不保證是否在onPause()之前或者之后觸發。

Fragment的生命周期以及與Activity之間的關系

注意和Activity相比的區別:

  • onAttach() onDetach()
  • onCreateView() onDestoryView()

Intent的使用方法,可以傳遞哪些數據類型?

通過查詢Intent/Bundle的API文檔,我們可以知道,Intent/Bundle支持傳遞基本類型的數據和基本類型的數組數據,以及String/CharSequence類型的數據和String/CharSequence類型的數組數據。而對于其他類型的數據或數組數據則可以使對象序列化,例如實現Parcelable接口或實現Serializable接口。


為什么在Service中創建子線程而不是在Activity中?

這是因為Activity很難對Thread進行控制,當Activity被銷毀之后,就沒有任何其它的辦法可以再重新獲取到之前創建的子線程的實例。而且在一個Activity中創建的子線程,另一個Activity無法對其進行操作。但是Service就不同了,所有的Activity都可以與Service進行關聯,然后可以很方便地操作其中的方法,即使Activity被銷毀了,之后只要重新與Service建立關聯,就又能夠獲取到原有的Service中Binder的實例。因此,使用Service來處理后臺任務,Activity就可以放心地finish,完全不需要擔心無法對后臺任務進行控制的情況。


Service的兩種啟動方法是?有什么區別?

1.在Context中通過public boolean bindService(Intent service, ServiceConnectionconn, int flags)方法來進行Service與Context的關聯并啟動,并且Service的生命周期依附于Context(不求同年同月同日生,但求同年同月同日死)。
2.通過public ComponentName startService(Intent service)方法去啟動一個Service,此時Service的生命周期與啟動它的Context無關。
3.要注意的是無論如何,都需要在AndroidManifest.xml里注冊你的Service

<service
    android:name=".packnameName.youServiceName"
    android:enabled="true" />

廣播(Broadcast Receiver)的兩種動態注冊和靜態注冊有什么區別?
  • 靜態注冊:在AndroidManifest.xml文件中進行注冊,當App退出后,Receiver仍然可以接收到廣播并且進行相應的處理。
  • 動態注冊:在代碼中動態注冊,當App退出后,也就沒辦法在接受廣播了。

保證Service不被殺死的幾種方法

1.Service設置成START_STICKY

  • kill后會被重啟(等待5秒左右),重傳Intent,保持與重啟前一樣。

2.提升Service的優先級

  • 在AndroidManifest.xml文件中對于intent-file可以通過android:proiority = "1000"這個屬性設置最高優先級,1000是最高值,如果數字越小則優先級越低,同樣適用于廣播
  • 【結論】目前看來,priority這個屬性貌似只適用于Broadcast,對于Service來說無效。

3.onDestroy方法里重啟Service

  • Service + Broadcast 方式,就是當Service執行onDestory()的時候,發送一個自定義的廣播,當收到廣播的時候,重新啟動service。
  • 也可以直接在onDestroy()里startService
  • 【結論】當使用助手類軟件或者直接在設置里強制停止應用時,App進程直接被結束,onDestroy方法都進不來,還是無法徹底保證。

4.監聽系統廣播判斷Service狀態

  • 通過系統的一些廣播,比如:手機重啟、界面喚醒、應用狀態改變等等監聽并捕獲到,然后判斷我們的Service是否還存活。
  • 【結論】這也能算是一種措施,不過見聽多了會導致Service很混亂,不方便。

5.root之后放到System/app變成系統級應用

6.放一個像素在前臺


如何判斷應用被強殺

在Application中定義一個Static常量,賦值為-1,在Splash界面改為0,如果被強殺,application重新初始化,在父類Activity判斷該常量的值。

應用被強殺如何解決

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

Asset目錄與res目錄的區別

res 目錄下面有很多文件,例如 drawable,mipmap,raw 等。res 下面除了 raw 文件不會被壓縮外,其余文件都會被壓縮。同時 res目錄下的文件可以通過R 文件訪問。Asset 也是用來存儲資源,但是 asset 文件內容只能通過路徑或者 AssetManager 讀取。

Android怎么加速啟動Activity

啟動應用 :Application 的構造方法,onCreate 方法中不要進行耗時操作,數據預讀取(例如 init 數據) 放在異步中操作
啟動普通的Activity:A 啟動B 時不要在 A 的 onPause 中執行耗時操作。因為 B 的 onResume 方法必須等待 A 的 onPause 執行完成后才能運行

Android內存優化方法:ListView優化,及時關閉資源,圖片緩存等等。

View和View Group的區別?自定義View的過程?
  • Android的UI界面都是由View和ViewGroup及其派生類組合而成的。其中,View是所有UI組件的基類,而 ViewGroup是容納這些組件的容器,其本身也是從View派生出來的。View對象是Android平臺中用戶界面體現的基礎單位。View類是它稱為“widgets(工具)”的子類的基礎,它們提供了諸如文本輸入框和按鈕之類的UI對象的完整實現。ViewGroup類同樣為其被稱為“Layouts(布局)”的子類奠定了基礎,它們提供了象流式布局、表格布局以及相對布局之類的布局架構。

  • 如何自定義控件:
    1.自定義屬性的聲明和獲取

    • 分析需要的自定義屬性
    • 在res/values/attrs.xml定義聲明
    • 在layout文件中進行使用
    • 在View的構造方法中進行獲取

    2.測量onMeasure
    3.布局onLayout(ViewGroup)
    4.繪制onDraw
    5.onTouchEvent
    6.onInterceptTouchEvent(ViewGroup)
    7.狀態的恢復與保存


Content的區別
  • Activity和Service以及Application的Context是不一樣的,Activity繼承自ContextThemeWraper.其他的繼承自ContextWrapper
  • 每一個Activity和Service以及Application的Context都是一個新的ContextImpl對象
  • getApplication()用來獲取Application實例的,但是這個方法只有在Activity和Service中才能調用的到。那么也許在絕大多數情況下我們都是在Activity或者Service中使用Application的,但是如果在一些其它的場景,比如BroadcastReceiver中也想獲得Application的實例,這時就可以借助getApplicationContext()方法,getApplicationContext()比getApplication()方法的作用域會更廣一些,任何一個Context的實例,只要調用getApplicationContext()方法都可以拿到我們的Application對象。
  • Activity在創建的時候會new一個ContextImpl對象并在attach方法中關聯它,Application和Service也差不多。ContextWrapper的方法內部都是轉調ContextImpl的方法
  • 創建對話框傳入Application的Context是不可以的
  • 盡管Application、Activity、Service都有自己的ContextImpl,并且每個ContextImpl都有自己的mResources成員,但是由于它們的mResources成員都來自于唯一的ResourcesManager實例,所以它們看似不同的mResources其實都指向的是同一塊內存
  • Context的數量等于Activity的個數 + Service的個數 + 1,這個1為Application

IntentService的使用場景與特點

IntentService是Service的子類,是一個異步的,會自動停止的服務,很好解決了傳統的Service中處理完耗時操作忘記停止并銷毀Service的問題
優點:

  • 一方面不需要自己去new Thread
  • 另一方面不需要考慮在什么時候關閉該Service
    onStartCommand中回調了onStart,onStart中通過mServiceHandler發送消息到該handler的handleMessage中去。最后handleMessage中回調onHandleIntent(intent)。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容