Android面試題之Android部分

1. Activity 系列問題

1.1 繪製Activity生命週期流程圖

Activity生命週期

1.2 介紹下不同場景下Activity生命週期的變化過程

  • 啓動Activity: onCreate()—>onStart()—>onResume(),Activity進入運行狀態。
  • Activity退居後臺: 當前Activity轉到新的Activity界面或按Home鍵回到主屏:
    onPause()—>onStop(),進入停滯狀態。
  • Activity返回前臺: onRestart()—>onStart()—>onResume(),再次回到運行狀態。
  • Activity退居後臺,且系統內存不足, 系統會殺死這個後臺狀態的Activity,若再次回到這個Activity,則會走onCreate()–>onStart()—>onResume()
  • 鎖定屏與解鎖屏幕 只會調用onPause(),而不會調用onStop方法,開屏後則調用onResume()

1.3 內存不足時系統會殺掉後臺的Activity,若需要進行一些臨時狀態的保存,在哪個方法進行?

Activity的 onSaveInstanceState() 和 onRestoreInstanceState()並不是生命週期方法,它們不同於 onCreate()、onPause()等生命週期方法,它們並不一定會被觸發。當應用遇到意外情況(如:內存不足、用戶直接按Home鍵)由系統銷燬一個Activity,onSaveInstanceState() 會被調用。但是當用戶主動去銷燬一個Activity時,例如在應用中按返回鍵,onSaveInstanceState()就不會被調用。除非該activity是被用戶主動銷燬的,通常onSaveInstanceState()只適合用於保存一些臨時性的狀態,而onPause()適合用於數據的持久化保存。

1.4 onSaveInstanceState()被執行的場景有哪些:

系統不知道你按下HOME後要運行多少其他的程序,自然也不知道activity A是否會被銷燬,因此係統都會調用onSaveInstanceState(),讓用戶有機會保存某些非永久性的數據。以下幾種情況的分析都遵循該原則

  • 當用戶按下HOME鍵時
  • 長按HOME鍵,選擇運行其他的程序時
  • 鎖屏時
  • 從activity A中啓動一個新的activity時
  • 屏幕方向切換時

1.5 介紹Activity的幾中啓動模式,並簡單說說自己的理解或者使用場景

Activity中的四種啓動模式

2. Service系列問題

2.1 註冊Service需要注意什麼

Service還是運行在主線程當中的,所以如果需要執行一些複雜的邏輯操作,最好在服務的內部手動創建子線程進行處理,否則會出現UI線程被阻塞的問題

2.2 Service與Activity怎麼實現通信

方法一:

添加一個繼承Binder的內部類,並添加相應的邏輯方法
重寫Service的onBind方法,返回我們剛剛定義的那個內部類實例
Activity中創建一個ServiceConnection的匿名內部類,並且重寫裏面的onServiceConnected方法和onServiceDisconnected方法,這兩個方法分別會在活動與服務成功綁定以及解除綁定的時候調用,在onServiceConnected方法中,我們可以得到一個剛纔那個service的binder對象,通過對這個binder對象進行向下轉型,得到我們那個自定義的Binder實例,有了這個實例,做可以調用這個實例裏面的具體方法進行需要的操作了
方法二 通過BroadCast(廣播)的形式 當我們的進度發生變化的時候我們發送一條廣播,然後在Activity的註冊廣播接收器,接收到廣播之後更新視圖

2.3 介紹源碼中binder機制這裏寫代碼片

Android深入淺出之Binder機制
Android實戰技術:理解Binder機制

2.4 IntentService與Service的區別

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

會創建獨立的worker線程來處理所有的Intent請求;
會創建獨立的worker線程來處理onHandleIntent()方法實現的代碼,無需處理多線程問題;
所有請求處理完成後,IntentService會自動停止,無需調用stopSelf()方法停止Service;
爲Service的onBind()提供默認實現,返回null;
爲Service的onStartCommand提供默認實現,將請求Intent添加到隊列中;
IntentService不會阻塞UI線程,而普通Serveice會導致ANR異常
Intentservice若未執行完成上一次的任務,將不會新開一個線程,是等待之前的任務完成後,再執行新的任務,等任務完成後再次調用stopSelf()

3. Handle系列問題

3.1 介紹Handle的機制

Handler通過調用sendmessage方法把消息放在消息隊列MessageQueue中,Looper負責把消息從消息隊列中取出來,重新再交給Handler進行處理,三者形成一個循環
通過構建一個消息隊列,把所有的Message進行統一的管理,當Message不用了,並不作爲垃圾回收,而是放入消息隊列中,供下次handler創建消息時候使用,提高了消息對象的複用,減少系統垃圾回收的次數
每一個線程,都會單獨對應的一個looper,這個looper通過ThreadLocal來創建,保證每個線程只創建一個looper,looper初始化後就會調用looper.loop創建一個MessageQueue,這個方法在UI線程初始化的時候就會完成,我們不需要手動創建

3.2 談談對HandlerThread的理解

4. ListView系列問題

4.1 ListView卡頓的原因與性能優化,越多越好

重用converView: 通過複用converview來減少不必要的view的創建,另外Infalte操作會把xml文件實例化成相應的View實例,屬於IO操作,是耗時操作。

減少findViewById()操作: 將xml文件中的元素封裝成viewholder靜態類,通過converview的setTag和getTag方法將view與相應的holder對象綁定在一起,避免不必要的findviewbyid操作

避免在 getView 方法中做耗時的操作: 例如加載本地 Image 需要載入內存以及解析 Bitmap ,都是比較耗時的操作,如果用戶快速滑動listview,會因爲getview邏輯過於複雜耗時而造成滑動卡頓現象。用戶滑動時候不要加載圖片,待滑動完成再加載,可以使用這個第三方庫glide

Item的佈局層次結構儘量簡單,避免佈局太深或者不必要的重繪

儘量能保證 Adapter 的 hasStableIds() 返回 true 這樣在 notifyDataSetChanged() 的時候,如果item內容並沒有變化,ListView 將不會重新繪製這個 View,達到優化的目的

在一些場景中,ScollView內會包含多個ListView,可以把listview的高度寫死固定下來。 由於ScollView在快速滑動過程中需要大量計算每一個listview的高度,阻塞了UI線程導致卡頓現象出現,如果我們每一個item的高度都是均勻的,可以通過計算把listview的高度確定下來,避免卡頓現象出現

使用 RecycleView 代替listview: 每個item內容的變動,listview都需要去調用notifyDataSetChanged來更新全部的item,太浪費性能了。RecycleView可以實現當個item的局部刷新,並且引入了增加和刪除的動態效果,在性能上和定製上都有很大的改善

ListView 中元素避免半透明: 半透明繪製需要大量乘法計算,在滑動時不停重繪會造成大量的計算,在比較差的機子上會比較卡。 在設計上能不半透明就不不半透明。實在要弄就把在滑動的時候把半透明設置成不透明,滑動完再重新設置成半透明。

儘量開啓硬件加速: 硬件加速提升巨大,避免使用一些不支持的函數導致含淚關閉某個地方的硬件加速。當然這一條不只是對 ListView。

4.2 怎麼實現一個部分更新的 ListView?

http://blog.csdn.net/tianjia1872954551/article/details/52209787

4.3 怎麼實現ListView多種佈局?

4.4 ListView與數據庫綁定的實現

5. JNI系列問題

5.1 如何使用JNI

JAVA中聲明native 方法如private native String printJNI(String inputStr);

使用javah工具生成.h頭文件這時候頭文件中就會自動生成對應的函數JNIEXPORT jstring JNICALL Java_com_wenming_HelloWorld_printJNI

實現JNI原生函數源文件,新建HelloWorld.c文件,對剛纔自動生成的函數進行具體的邏輯書寫,例如返回一個java叫做HelloWorld的字符串等

編譯生成動態鏈接so文件**

Java中調用Sysytem.load方法把剛纔的so庫加載進來,就可以調用native方法了

5.2 如何通過JNI傳遞String對象

Java的String和C++的string是不能對等起來的,所以當我們拿到.h文件下面的jstring對象,會做一次轉換我們把jstring轉換爲C下面的char*類型, 獲取值

constchar* str;
str = env->GetStringUTFChars(prompt,false);
賦予值

char* tmpstr =”return string succeeded”;
jstring rtstr = env->NewStringUTF(tmpstr);

6. OOM系列問題

6.1 什麼OOM?

OOM全稱是Out Of Merrory,Android系統的每一個應用程序都設置一個硬性的Dalvik Heap Size最大限制閾值,如果申請的內存資源超過這個限制,系統就會拋出OOM錯誤

6.2 內存泄漏有哪些場景以及解決方法

類的靜態變量持有大數據對象 靜態變量長期維持到大數據對象的引用,阻止垃圾回收。

非靜態內部類存在靜態實例 非靜態內部類會維持一個到外部類實例的引用,如果非靜態內部類的實例是靜態的,就會間接長期維持着外部類的引用,阻止被回收掉。

資源對象未關閉 資源性對象比如(Cursor,File文件等)往往都用了一些緩衝,我們在不使用的時候,應該及時關閉它們, 以便它們的緩衝及時回收內存。它們的緩衝不僅存在於java虛擬機內,還存在於java虛擬機外。 如果我們僅僅是把它的引用設置爲null,而不關閉它們,往往會造成內存泄露。 解決辦法: 比如SQLiteCursor(在析構函數finalize(),如果我們沒有關閉它,它自己會調close()關閉), 如果我們沒有關閉它,系統在回收它時也會關閉它,但是這樣的效率太低了。 因此對於資源性對象在不使用的時候,應該調用它的close()函數,將其關閉掉,然後才置爲null. 在我們的程序退出時一定要確保我們的資源性對象已經關閉。 程序中經常會進行查詢數據庫的操作,但是經常會有使用完畢Cursor後沒有關閉的情況。如果我們的查詢結果集比較小, 對內存的消耗不容易被發現,只有在常時間大量操作的情況下才會復現內存問題,這樣就會給以後的測試和問題排查帶來困難和風險,記得try catch後,在finally方法中關閉連接

Handler內存泄漏 Handler作爲內部類存在於Activity中,但是Handler生命週期與Activity生命週期往往並不是相同的,比如當Handler對象有Message在排隊,則無法釋放,進而導致本該釋放的Acitivity也沒有辦法進行回收。 解決辦法:

聲明handler爲static類,這樣內部類就不再持有外部類的引用了,就不會阻塞Activity的釋放
如果內部類實在需要用到外部類的對象,可在其內部聲明一個弱引用引用外部類。

public class MainActivity extends Activity {
 private CustomHandler mHandler;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     mHandler = new CustomHandler(this);
 }

 static class CustomHandlerextends Handler {
     // 內部聲明一個弱引用,引用外部類
     private WeakReference<MainActivity > activityWeakReference;
     public MyHandler(MyActivity activity) {
         activityWeakReference= new WeakReference<MainActivity >(activity);
     }
             // ... ...   
 }
}

在Activity onStop或者onDestroy的時候,取消掉該Handler對象的Message和Runnable

Override
public void onDestroy() {
 //  If null, all callbacks and messages will be removed.
 mHandler.removeCallbacksAndMessages(null);
}

一些不良代碼習慣 有些代碼並不造成內存泄露,但是他們的資源沒有得到重用,頻繁的申請內存和銷燬內存,消耗CPU資源的同時,也引起內存抖動 解決方案 如果需要頻繁的申請內存對象和和釋放對象,可以考慮使用對象池來增加對象的複用。 例如ListView便是採用這種思想,通過複用converview來避免頻繁的GC

6.3 如何避免 OOM 問題的出現

  1. 使用更加輕量的數據結構 例如,我們可以考慮使用ArrayMap/SparseArray而不是HashMap等傳統數據結構。通常的HashMap的實現方式更加消耗內存,因爲它需要一個額外的實例對象來記錄Mapping操作。另外,SparseArray更加高效,在於他們避免了對key與value的自動裝箱(autoboxing),並且避免了裝箱後的解箱。

  2. 避免在Android裏面使用Enum Android官方培訓課程提到過“Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.”,具體原理請參考《Android性能優化典範(三)》,所以請避免在Android裏面使用到枚舉。

  3. 減小Bitmap對象的內存佔用 Bitmap是一個極容易消耗內存的大胖子,減小創建出來的Bitmap的內存佔用可謂是重中之重,,通常來說有以下2個措施: inSampleSize:縮放比例,在把圖片載入內存之前,我們需要先計算出一個合適的縮放比例,避免不必要的大圖載入。 decode format:解碼格式,選擇ARGB_6666/RBG_545/ARGB_4444/ALPHA_6,存在很大差異

  4. Bitmap對象的複用 縮小Bitmap的同時,也需要提高BitMap對象的複用率,避免頻繁創建BitMap對象,複用的方法有以下2個措施 LRUCache : “最近最少使用算法”在Android中有極其普遍的應用。ListView與GridView等顯示大量圖片的控件裏,就是使用LRU的機制來緩存處理好的Bitmap,把近期最少使用的數據從緩存中移除,保留使用最頻繁的數據, inBitMap高級特性:利用inBitmap的高級特性提高Android系統在Bitmap分配與釋放執行效率。使用inBitmap屬性可以告知Bitmap解碼器去嘗試使用已經存在的內存區域,新解碼的Bitmap會嘗試去使用之前那張Bitmap在Heap中所佔據的pixel data內存區域,而不是去問內存重新申請一塊區域來存放Bitmap。利用這種特性,即使是上千張的圖片,也只會僅僅只需要佔用屏幕所能夠顯示的圖片數量的內存大小

  5. 使用更小的圖片 在涉及給到資源圖片時,我們需要特別留意這張圖片是否存在可以壓縮的空間,是否可以使用更小的圖片。儘量使用更小的圖片不僅可以減少內存的使用,還能避免出現大量的InflationException。假設有一張很大的圖片被XML文件直接引用,很有可能在初始化視圖時會因爲內存不足而發生InflationException,這個問題的根本原因其實是發生了OOM。

  6. StringBuilder 在有些時候,代碼中會需要使用到大量的字符串拼接的操作,這種時候有必要考慮使用StringBuilder來替代頻繁的“+”。

  7. 避免在onDraw方法裏面執行對象的創建 類似onDraw等頻繁調用的方法,一定需要注意避免在這裏做創建對象的操作,因爲他會迅速增加內存的使用,而且很容易引起頻繁的gc,甚至是內存抖動。

  8. 避免對象的內存泄露 android中內存泄漏的場景以及解決辦法,參考上一問

7. ANR 系列問題

7.1 什麼ANR

ANR全稱Application Not Responding,意思就是程序未響應。如果一個應用無法響應用戶的輸入,系統就會彈出一個ANR對話框,用戶可以自行選擇繼續等待亦或者是停止當前程序。一旦出現下面兩種情況,則彈出ANR對話框

應用在5秒內未響應用戶的輸入事件(如按鍵或者觸摸)
BroadcastReceiver未在10秒內完成相關的處理

7.2 ANR是怎麼引起的?

主線程中存在耗時的計算-
主線程被IO操作(從4.0之後網絡IO不允許在主線程中)阻塞。-
主線程中錯誤的操作,比如Thread.wait或者Thread.sleep等

7.3 如何避免ANR問題的出現

基本思路就是把一些耗時操作放到子線程中處理

使用AsyncTask處理耗時IO操作。

降低子線程優先級使用Thread或者HandlerThread時,調用Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)設置優先級,否則仍然會降低程序響應,因爲默認Thread的優先級和主線程相同。

使用Handler處理子線程結果,而不是使用Thread.wait()或者Thread.sleep()來阻塞主線程。

Activity的onCreate和onResume回調中儘量避免耗時的代碼

BroadcastReceiver中onReceive代碼也要儘量減少耗時操作建議使用IntentService處理。IntentService是一個異步的,會自動停止的服務,很好解決了傳統的Service中處理完耗時操作忘記停止並銷燬Service的問題

8. Asynctask問題

8.1 AsynTask爲什麼要設計爲只能夠一次任務?

最核心的還是線程安全問題,多個子線程同時運行,會產生狀態不一致的問題。所以要務必保證只能夠執行一次

8.2 AsynTask造成的內存泄露的問題怎麼解決?

比如非靜態內部類AsynTask會隱式地持有外部類的引用,如果其生命週期大於外部activity的生命週期,就會出現內存泄漏

注意要複寫AsynTask的onCancel方法,把裏面的socket,file等,該關掉的要及時關掉
在 Activity 的onDestory()方法中調用Asyntask.cancal方法
Asyntask內部使用弱引用的方式來持有Activity

8.3 若Activity已經銷燬,此時AsynTask執行完並且返回結果,會報異常嗎?

當一個App旋轉時,整個Activity會被銷燬和重建。當Activity重啓時,AsyncTask中對該Activity的引用是無效的,因此onPostExecute()就不會起作用,若AsynTask正在執行,折會報 view not attached to window manager 異常

同樣也是生命週期的問題,在 Activity 的onDestory()方法中調用Asyntask.cancal方法,讓二者的生命週期同步

8.4 Activity銷燬但Task如果沒有銷燬掉,當Activity重啓時這個AsyncTask該如何解決?

還是屏幕旋轉這個例子,在重建Activity的時候,會回掉Activity.onRetainNonConfigurationInstance()重新傳遞一個新的對象給AsyncTask,完成引用的更新

9. Android觸摸分發機制

9.1 介紹觸摸事件的分發機制

觸摸事件調用機制

(1) 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View可以通過onTouchEvent()對事件進行處理。

(2) 事件由父View(ViewGroup)傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。

(3) 如果事件從上往下傳遞過程中一直沒有被停止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)可以進行消費,如果還是沒有被消費的話,最後會到Activity的onTouchEvent()函數。

(4) 如果View沒有對ACTION_DOWN進行消費,之後的其他事件不會傳遞過來。

(5) OnTouchListener優先於onTouchEvent()對事件進行消費。

上面的消費即表示相應函數返回值爲true。

9.2 View中 setOnTouchListener的onTouch,onTouchEvent,onClick的執行順序

追溯到View的dispatchTouchEvent源碼查看,有這麼一段代碼

public boolean dispatchTouchEvent(MotionEvent event) {  
    if (!onFilterTouchEventForSecurity(event)) {  
        return false;  
    }  

    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
            mOnTouchListener.onTouch(this, event)) {  
        return true;  
    }  
    return onTouchEvent(event);  
 }

當以下三個條件任意一個不成立時,

mOnTouchListener不爲null
view是enable的狀態
mOnTouchListener.onTouch(this, event)返回true,
函數會執行到onTouchEvent。在這裏我們可以看到,首先執行的是mOnTouchListener.onTouch的方法,然後是onTouchEvent方法

繼續追溯源碼,到onTouchEvent()觀察,發現在處理ACTION_UP事件裏有這麼一段代碼

if (!post(mPerformClick)) {  
    performClick();  
}

此時可知,onClick方法也在最後得到了執行

所以三者的順序是:

setOnTouchListener() 的onTouch
onTouchEvent()
onClick()

10. Dalvik虛擬機系列問題

10.1 什麼是Dalvik虛擬機?

Dalvik虛擬機是Android平臺的核心。它可以支持.dex格式的程序的運行,.dex格式是專爲Dalvik設計的一種壓縮格式,可以減少整體文件尺寸,提高I/O操作的速度,適合內存和處理器速度有限的系統。

10.2 Dalvik虛擬機的作用是什麼?

Dalvik虛擬機主要是完成對象生命週期管理,內存回收,堆棧管理,線程管理,安全和異常管理等等重要功能。

10.3 Dalvik虛擬機與JVM有什麼區別

Dalvik 基於寄存器,而 JVM 基於棧。基於寄存器的虛擬機對於更大的程序來說,在它們編譯的時候,花費的時間更短。
Dalvik執行.dex格式的字節碼,而JVM執行.class格式的字節碼。

10.4 每個應用程序對應多少個Dalvik虛擬機

每一個Android應用在底層都會對應一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執行 ,而所有的Android應用的線程都對應一個Linux線程

11. 註冊廣播接收器有哪幾種方式,有什麼區別

靜態註冊:在AndroidManifest.xml文件中進行註冊,當App退出後,Receiver仍然可以接收到廣播並且進行相應的處理
動態註冊:在代碼中動態註冊,當App退出後,也就沒辦法再接受廣播了

12. 顯示Intent與隱式Intent的區別

對明確指出了目標組件名稱的Intent,我們稱之爲“顯式Intent”。 對於沒有明確指出目標組件名稱的Intent,則稱之爲“隱式 Intent”。

對於隱式意圖,在定義Activity時,指定一個intent-filter,當一個隱式意圖對象被一個意圖過濾器進行匹配時,將有三個方面會被參考到:

動作(Action)
類別(Category [‘kætɪg(ə)rɪ] )
數據(Data )

13. Android中的動畫有哪些,區別是什麼

逐幀動畫(Drawable Animation): 加載一系列Drawable資源來創建動畫,簡單來說就是播放一系列的圖片來實現動畫效果,可以自定義每張圖片的持續時間

補間動畫(Tween Animation): Tween可以對View對象實現一系列簡單的動畫效果,比如位移,縮放,旋轉,透明度等等。但是它並不會改變View屬性的值,只是改變了View的繪製的位置,比如,一個按鈕在動畫過後,不在原來的位置,但是觸發點擊事件的仍然是原來的座標。

屬性動畫(Property Animation): 動畫的對象除了傳統的View對象,還可以是Object對象,動畫結束後,Object對象的屬性值被實實在在的改變了

14. 不使用動畫,怎麼實現一個動態的 View?

15. Postvalidata與Validata有什麼區別?

16. 如何自定義ViewGroup?

17. View的繪製流程

View繪製流程

measure()方法,layout(),draw()三個方法主要存放了一些標識符,來判斷每個View是否需要再重新測量,佈局或者繪製,主要的繪製過程還是在onMeasure,onLayout,onDraw這個三個方法中

  1. onMesarue() 爲整個View樹計算實際的大小,即設置實際的高(對應屬性:mMeasuredHeight)和寬(對應屬性: mMeasureWidth),每個View的控件的實際寬高都是由父視圖和本身視圖決定的。

  2. onLayout() 爲將整個根據子視圖的大小以及佈局參數將View樹放到合適的位置上。

  3. onDraw() 開始繪製圖像,繪製的流程如下:
    首先繪製該View的背景
    調用onDraw()方法繪製視圖本身 (每個View都需要重載該方法,ViewGroup不需要實現該方法)
    如果該View是ViewGroup,調用dispatchDraw ()方法繪製子視圖
    繪製滾動條

18. 數據持久化的四種方式有哪些?

文件存儲: 通過java.io.FileInputStream和java.io.FileOutputStream這兩個類來實現對文件的讀寫,java.io.File類則用來構造一個具體指向某個文件或者文件夾的對象。

SharedPreferences: SharedPreferences是一種輕量級的數據存儲機制,他將一些簡單的數據類型的數據,包括boolean類型,int類型,float類型,long類型以及String類型的數據,以鍵值對的形式存儲在應用程序的私有Preferences目錄(/data/data/<包名>/shared_prefs/)中,這種Preferences機制廣泛應用於存儲應用程序中的配置信息。

SQLite數據庫: 當應用程序需要處理的數據量比較大時,爲了更加合理地存儲、管理、查詢數據,我們往往使用關係數據庫來存儲數據。Android系統的很多用戶數據,如聯繫人信息,通話記錄,短信息等,都是存儲在SQLite數據庫當中的,所以利用操作SQLite數據庫的API可以同樣方便的訪問和修改這些數據。

ContentProvider: 主要用於在不同的應用程序之間實現數據共享的功能,不同於sharepreference和文件存儲中的兩種全局可讀寫操作模式,內容提供其可以選擇只對哪一部分數據進行共享,從而保證我們程序中的隱私數據不會有泄漏的風險

19. fragement裏面可以再嵌套fragment?

20. Socker編程的步驟

21. Activity中如何動態的添加Fragment

22. Scrollview怎麼判斷是否滑倒底部

23. 什麼是 MVC 模式?MVC 模式的好處是什麼?

24. 應用常駐後臺,避免被第三方殺掉的方法,講講你用過的奇淫巧技?

Service設置成START_STICKY kill 後會被重啓(等待5秒左右),重傳Intent,保持與重啓前一樣

通過 startForeground將進程設置爲前臺進程, 做前臺服務,優先級和前臺應用一個級別​,除非在系統內存非常缺,否則此進程不會被 kill

雙進程Service: 讓2個進程互相保護**,其中一個Service被清理後,另外沒被清理的進程可以立即重啓進程

QQ黑科技: 在應用退到後臺後,另起一個只有 1 像素的頁面停留在桌面上,讓自己保持前臺狀態,保護自己不被後臺清理工具殺死

在已經root的設備下,修改相應的權限文件,將App僞裝成系統級的應用 Android4.0系列的一個漏洞,已經確認可行

用C編寫守護進程(即子進程) : Android系統中當前進程(Process)fork出來的子進程,被系統認爲是兩個不同的進程。當父進程被殺死的時候,子進程仍然可以存活,並不受影響。鑑於目前提到的在Android->- Service層做雙守護都會失敗,我們可以fork出c進程,多進程守護。死循環在那檢查是否還存在,具體的思路如下(Android5.0以上的版本不可行)
用C編寫守護進程(即子進程),守護進程做的事情就是循環檢查目標進程是否存在,不存在則啓動它。
在NDK環境中將1中編寫的C代碼編譯打包成可執行文件(BUILD_EXECUTABLE)。主進程啓動時將守護進程放入私有目錄下,賦予可執行權限,啓動它即可。

聯繫廠商,加入白名單

25.Context與ApplicationContext的區別,分別用在什麼情況下

Application的Context是一個全局靜態變量,SDK的說明是隻有當你引用這個context的生命週期超過了當前activity的生命週期,而和整個應用的生命週期掛鉤時,纔去使用這個application的context。

在android中context可以作很多操作,但是最主要的功能是加載和訪問資源。在android中有兩種context,一種是 application context,一種是activity context,通常我們在各種類和方法間傳遞的是activity context。

26. 同一個應用程序的不同Activity可以運行在不同的進程中麼?如果可以,舉例說明;

27. Java中的線程同步有哪幾種方式,舉例說明;

28. dp, dip, dpi, px, sp是什麼意思以及他們的換算公式?layout-sw400dp, layout-h400dp分別代表什麼意思;

29. 如何讓兩個TextView在一個RelativeLayout水平居中顯示;

30. 如何畫出一個印章的圖案

31. 如何實現一個字體的描邊與陰影效果

32. 設計一個從網絡請求數據,圖片,並加載到列表的系統,畫出客戶端架構並簡單的分析下;

33. 設計一個文件的斷點續傳系統;

34. 設計一個圖片緩存加載機制

發佈了26 篇原創文章 · 獲贊 5 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章