一、Activity的生命週期,緩存,啓動模式
1.Activity的一些生命週期
- 啓動Activity:onCreate()->onStart()->onResume()
- Activity退居後臺:跳轉或者HOME鍵,onPause()->onStop()
- Activity返回前臺:onRestart()->onStart()->onResume()
2.進行一些臨時狀態的保存,在哪個方法進行?
Activity的onSaveInstanceState()和onRestoreInstanceState()並不是生命週期方法。內存不足、用戶按HOME鍵等,由系統銷燬一個Activity,onSaveInstanceState()會被調用。但用戶主動去銷燬Activity,如按返回鍵,則onSaveInstanceState()不會調用。通常onSaveInstanceState()只適合用於保存臨時的狀態,而onPause()適合數據的持久化保存。getLastCustomNonConfigurationInstance()和onRetainCustomNonConfigurationInstance(),保存橫豎屏狀態以及保存大的對象。
3.Acitivty的四中啓動模式與特點。
- standard模式,默認模式,採取壓棧的方式,一直創建
- singletop模式,如果發現棧頂已經存在,則不創建,複用
- singleTask模式,如果發現棧中已經存在,則不創建, 複用,並把上面的Activity銷燬
- singInstance模式,新建一個任務棧,詳細:http://blog.csdn.net/liuhe688/article/details/6754323/。
二、Service的生命週期,兩種啓動方法,有什麼區別。
1.Service的一些生命週期
- 採用startService()開啓服務:
onCreate()->onStartCommand()->onDestory()
與綁定者無關 - 採用bind開啓服務:
onCreate() —>onBind()—>onunbind()—>onDestory()
不會調用onStartCommand()
與綁定者相同銷燬
2.怎麼保證service不被殺死。
- WakeLock
PowerManager mgr = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
- onStartCommand方法,返回START_STICKY
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
flags = START_STICKY;
return super.onStartCommand(intent, flags, startId);
}
- 提升service優先級
<service
android:name="com.dbjtech.acbxt.waiqin.UploadService"
android:enabled="true" >
<intent-filter android:priority="1000" >
<action android:name="com.dbjtech.myservice" />
</intent-filter>
</service>
- 提升service進程優先級
依次銷燬:
1.前臺進程( FOREGROUND_APP)
2.可視進程(VISIBLE_APP )
3.次要服務進程(SECONDARY_SERVER )
4.後臺進程 (HIDDEN_APP)
5.內容供應節點(CONTENT_PROVIDER)
6.空進程(EMPTY_APP)
谷歌官方推薦,使用notification將服務變成前臺進程
Service.startForeground()
- onDestroy方法裏重啓service,或者廣播進行重啓
三、Broadcast的兩種註冊方法,有什麼區別。
1.常駐型廣播
當你的應用程序關閉了,如果有廣播信息來,你寫的廣播接收器同樣的能接收到,在AndroidManifast.xml進行註冊,又稱爲靜態註冊。當BroadcastReceiver更新UI,通常會使用這樣的方法註冊。啓動Activity時候註冊BroadcastReceiver,Activity不可見時候,取消註冊。
<!-- 監聽開機廣播 -->
<receiver android:name=".receiver.BootCompleteReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
2.常駐型廣播
非常駐型廣播,當應用程序結束,廣播就沒有了,一般在onCreate()和onResume()註冊廣播接收者,在onDestory()銷燬,也叫動態註冊,與註冊者關聯在一起。使用這樣的方法註冊弊端:它會始終處於活動狀態,畢竟是手機開發,cpu和電源資源比較少,一直處於活動耗費大,不利。
broadcastReceiver receiver;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter();
//增加電量監聽
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(receiver, intentFilter);
}
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
class broadcastReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
Log.d("TAg","電量改變了");
}
}
四、Intent的使用方法,可以傳遞哪些數據類型。
1.Intent的使用方法
- 啓動Activity,使用startActivity()和startActivityForResult()。
- 啓動Service,使用startService()和bindService()。
- 發送廣播,使用sendBroadcast()發送無序廣播;使用sendOrderedBroadcast()發送有序廣播,根據intent-filter的android:priority屬性的優先級依次發送,可以中斷;sendStickyBroadcast()發送廣播,保存最後一次的intent。
2.Intent的類型
- explicit顯式,Intent中明確包含啓動的組件的完整類名。
- implict隱式,Intent中沒有包含要啓動的組件的完整類名,而是通過action,即在Intent Filter裏面進行匹配,如果有多個匹配,就出現多個選擇框。在5.0之後隱式的調用bindService()會拋出異常。
3.Intent的組成
- Android可以根據Intent所攜帶的信息去查找要啓動的組件,Intent還攜帶了一些數據信息以便要啓動的組件。
- 由六部分信息組成:Component Name, Action, Data, Catagory, Extras, Flags
- Component Name,你可以通過Intent的setComponent()、setClass()、setClassName()、或通過構造函數指定顯式的啓動。
- Action,對應Intent Filter中的action標籤,如Intent.ACTION_VIEW對應值爲“android.intent.action.View”,用於信息展示給其他Activity。Intent.ACTION_SEND對應值爲:“android.intent.action.SEND”,常用於分享。還有更多,如打開系統設置WALN等。
- Data,指Uri對象和數據的MIME類型,對應Intent Filter中的data標籤,一個完整的Uri由scheme、host、post、path組成,格式:://:/。當創建了一個Intent對象的時候,除了指定Uri之外,指定數據的MIME類型也很重要。例如,一個Activity能夠顯示圖片,但是不能夠播放視頻,顯示圖片的Uri和播放視頻的Uri可能很類似,爲了不讓Android誤將一個含有視頻Uri的Intent對象傳遞給一個只能顯示圖片的Activity,我們需要在該Activity的Intent Filter中指定MIME類型爲圖片(例如。如果只設置Uri需要調用Intent對象的setData(),如果只設置數據的MIME類型,需要調用Intent對象的setType(),如果同時設置Uri和MIME,則調用setDataAndType()。
- Category,包含如何處理Intent的一些其他信息,大多數Intent是不需要category的。CATEGORY_LAUNCHER用於標識某個App的入口Activity。
- Extra,使用putExtra(key, value)加入各種鍵值對形式的額外數據。
- Flags,標記的意思。flag會告知Android系統如何啓動Activity(例如,新啓動的Activity屬於哪個task),Intent對象的setFlags()
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
//設置MIME類型爲純文本。
sendIntent.setType("text/plain");
sendIntent.putExtra(Intent.EXTRA_TEXT, "li");
PackageManager pm = getPackageManager();
if (pm.resolveActivity(sendIntent, 0) != null){
startActivity(sendIntent);
/*
每次強制彈出選擇框,參考:http://www.jb51.net/article/76527.htm
Intent chooseIntent = sendIntent.createChooser(sendIntent, "title");
startActivity(chooseIntent);
*/
}
4.Intent傳遞的數據類型
- CharSequence接口,在JDK1.4中,引入了CharSequence接口(length();charAt(int index);subSequence(int start, int end);toString())。實現了這個接口的類有:CharBuffer、String、StringBuffer、StringBuilder這個四個類。
- Serializable,參考:http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html
- Parcelable,永久性保存對象,保存對象的字節序列到本地文件中;通過序列化對象在網絡中傳遞對象;通過序列化在進程間傳遞對象。
- Bundle:是將數據傳遞到另一個上下文中或保存或回覆你自己狀態的數據存儲方式。它的數據不是持久化狀態。
五、ContentProvider使用方法。
六、Touch事件分發機制。
- 例如button,在其繼承的view中dispatchTouchEvent()方法,觸摸就回調這個方法。並對觸摸監聽器的onTouch()的返回值進行判斷(我們自己會實現接口調用ontouch(),並return),onTouchEvent(event)方法會進行一系列觸摸switch判斷(如果是不可點擊直接在此方法中返回false,而不會進入判斷內容中),並在其中對點擊事件監聽performClick()(如果你進不來這個onTouchEvent方法,點擊事件就沒有用)。
- 例如LinearLayout,在其繼承的ViewGroup中onInterceptTouchEvent()
public boolean dispatchTouchEvent(MotionEvent event) {
if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
mOnTouchListener.onTouch(this, event)) {
return true;
}
return onTouchEvent(event);
}
參考:http://blog.csdn.net/duo2005duo/article/details/51604119
參考:http://blog.csdn.net/guolin_blog/article/details/9153747
1.touch監聽器沒被調用到?
a)如果是View非使能,直接用setEnabled(true)
b)如果是事件被這個View的viewparent攔截了。getParent().requestDisallowInterceptTouchEvent(false)
2.雙層滑動模塊嵌套後發生滑動不了的現象?
如果是事件被這個View的viewparent攔截了。可以修改這個viewparentonInterceptTouchTouchEvent(),或者在這個View中調用getParent().requestDisallowInterceptTouchEvent()
3.設置了onClickListener後,點擊View沒有反應?
看View.onTouchEvent()
a)如果是View非使能,直接用setEnabled(true)
b)可能覆蓋了onTouchEvent(),需要在覆蓋的方法調用super.onTouchEvent()或者手動調用performClick()
4.點擊兩下View才調用onClickListener的bug?
看View.onTouchEvent()
這個其實是安卓的設計,當某個View調用了setFocusableInTouchMode(true)後,第一次點擊會引起這個View的focus,第二次點擊纔會調用onClickListener,只需要設置setFocusableInTouchMode(false)即可。
七、Android內存優化方法:ListView優化,及時關閉資源,圖片緩存等等。
1.引用沒釋放造成的內存泄露
- 1.1註冊沒取消造成的內存泄露
- 1.2集合中對象沒清理造成的內存泄露
集合中:arrayList.trimToSize();
我們通常把一些對象的引用加入到了集合中,當我們不需要該對象時,並沒有把它的引用從集合中清理掉,這樣這個集合就會越來越大。如果這個集合是static的話,那情況就更嚴重了。
2.資源對象沒關閉造成的內存泄露
- 資源性對象比如(Cursor,File文件等)
3.一些不良代碼成內存壓力
- 3.1Bitmap沒調用recycle()。
雖然recycle()從源碼上看,調用它應該能立即釋放Bitmap的主要內存,但是測試結果顯示它並沒能立即釋放內存。但是我它應該還是能大大的加速Bitmap的主要內存的釋放。 - 3.2構造Adapter時,沒有使用緩存的 convertView
參考:http://www.cnblogs.com/kingOfPointer/archive/2012/12/21/2828018.html
八、View與View Group分類。自定義View過程:onMeasure()、onLayout()、onDraw()。
- 先進行onMeasure()進行測量大小,然後onLayout()選擇位置,onDraw()畫出具體的繪製。invalidate()會從當前view一直找到根view進行子view的重繪onDraw()。(requestLayout()會完全的走一遍繪製過程,不僅僅只是onDraw())。