一、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())。