Android笔记_2013_02_21
Android事件处理机制有两套:
基于监听的事件处理
基于回调的事件处理
先说一下事件处理的过程,事件处理主要涉及三个主要部分,事件源、事件、事件监听器,下面画个图解释一下他们之间的关系和事件处理的过程:
下面说说基于监听的事件处理
熟悉swing的都知道,这很简单,就是为事件源注册监听者,然后实现监听者接口就哦了
实现监听者有四种方法,下面分别说说四种方法的利弊:
一、外部类实现监听者
利:
基本没有
弊:
1、事件监听器通常属于特定的GUI界面,不利于程序的内聚性
2、外部类监听器不能随意访问GUI界面类中的组件,编程不够简洁
二、内部类实现监听者
利:
1、可以在当前类中复用该类
2、该类可以随意访问外部类中的组件
弊:
基本没有
三、匿名内部类实现监听者
利:
大部分时候事件处理器没有复用价值,匿名内部类正好
弊:
语法有点难度
四、Activity本身作为监听者
利:
基本没有
弊:
1、Activity本身应只负责界面类的初始化,不要多管闲事,违反单一功能原则
2、看着就乱
再说说基于回调的事件处理
实现方法:要通过自定义View来实现,在自定义View中重写该View的事件处理方法即可
例如:自定义MyButton继承自Button,覆盖onKeyDown方法,然后使用MyButton时发生keyDown事件就会调用此方法
好处:可以使内聚性更强
另外,Android中还可以在xml文件中以标签的形式绑定组件相应的事件处理函数
例如:
一个按钮<Button android:onClick="clickEvent".../>
在相应的Activity中定义clickEvent函数即可
好处:方便简洁
Activity生命周期管理之一——Starting一个Activity
3.创建一个新实例
Activity的生命周期完全由Android系统进行管理,周期中有几个主要的状态,下面介绍一下
下面一张图说的很清晰:
根据app的复杂性,不一定实现所有生命周期函数,但理解他们并知道什么时候该实现是很重要的,实现周期函数要保证一下几点:
· 接电话或转移到另一个app的时候不要产生冲突
· 用户不用时不要消耗可观的系统资源
· 在用户暂时离开时不要丢失用户数据和进展
· 屏幕方向改变时不要丢失用户数据
有三个状态时可以保持的:
Resumed
此状态下,activity在前台,可以和用户交互,也叫运行状态
Paused
此状态下,本activity被另一个前台activity隐藏,这个前台activity是半透明的或只占据部分屏幕,paused状态下activity不接受用户输入,也不执行任何代码
Stopped
此状态下,activity完全不可见,也就是在后台,所有实例对象和成员变量等都被保存,但不执行任何代码
其他状态都是瞬时的,调用onCreate后立即调用onStart后立即调用onResume
这些是基本的周期状态,下面看看一些特殊的生命周期表现
用户触点你的app icon时,系统调用被你声明为launcher activity的onCreate()函数,这个activity提供程序用户界面的主入口
可以在Android manifest文件中定义
launcher activity必须以<intent-filter>定义,包含MAIN action和LAUNCHER category标签,例如:
[html]view plaincopyprint?
1. <activityandroid:name=".MainActivity"android:label="@string/app_name">
2. <intent-filter>
3. <actionandroid:name="android.intent.action.MAIN"/>
4. <categoryandroid:name="android.intent.category.LAUNCHER"/>
5. </intent-filter>
6. </activity>
<activity android:name=".MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Note:使用Android SDK tools建立项目时,以上声明自动包含,如果没有MAIN action或LAUNCHER category,app icon不会出现在Home屏幕列表里
所有的新Activity实例产生都调用onCreate()函数
必须实现onCreate()函数做一些基本的初始化工作,例如用户界面初始化,成员变量初始化,或者UI的配置等等,例如下面例子:
[java]view plaincopyprint?
1. TextViewmTextView;//Membervariablefortextviewinthelayout
2.
3. @Override
4. publicvoidonCreate(BundlesavedInstanceState){
5. super.onCreate(savedInstanceState);
6.
7. //SettheuserinterfacelayoutforthisActivity
8. //Thelayoutfileisdefinedintheprojectres/layout/main_activity.xmlfile
9. setContentView(R.layout.main_activity);
10.
11. //InitializememberTextViewsowecanmanipulateitlater
12. mTextView=(TextView)findViewById(R.id.text_message);
13.
14. //Makesurewe'rerunningonHoneycomborhighertouseActionBarAPIs
15. if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB){
16. //Forthemainactivity,makesuretheappiconintheactionbar
17. //doesnotbehaveasabutton
18. ActionBaractionBar=getActionBar();
19. actionBar.setHomeButtonEnabled(false);
20. }
21. }
TextView mTextView; // Member variable for text view in the layout
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the user interface layout for this Activity
// The layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity);
// Initialize member TextView so we can manipulate it later
mTextView = (TextView) findViewById(R.id.text_message);
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// For the main activity, make sure the app icon in the action bar
// does not behave as a button
ActionBar actionBar = getActionBar();
actionBar.setHomeButtonEnabled(false);
}
}
Caution: 用SDK_INT以兼容Android2.0一下的版本,否则会出现运行时异常
技术上说,onStart()函数之后,界面可见,但onResume()函数调用紧随其后,所以看不出来
如下几种情况可以使activity脱离resumed状态:
1.来电话
2.用户转向另一个activity
3.屏幕被关掉
以后再说onStart()和onResume()函数何时使用,他们也是很有用的,特别对于经常从Paused和Stopped状态转换为Resumed状态的activity
Note: onCreate()的参数savedInstanceState后面再说
当app被完全移出内存之前,最后调用onDestroy()函数
大多数app不需要实现,因为大多清理工作会在onPause()和onStop()函数中做,然而,若果activity有后台线程或者其他不正确关闭会产生内存泄露的资源,要在onDestroy()函数中处理他们
[java]view plaincopyprint?
1. @Override
2. publicvoidonDestroy(){
3. super.onDestroy();//Alwayscallthesuperclass
4.
5. //StopmethodtracingthattheactivitystartedduringonCreate()
6. android.os.Debug.stopMethodTracing();
7. }
@Override
public void onDestroy() {
super.onDestroy(); // Always call the superclass
// Stop method tracing that the activity started during onCreate()
android.os.Debug.stopMethodTracing();
}
Note: 系统总是在onPause()和onStop()之后调用onDestroy(),但一种情况除外,就是在onCreate()中调用finish()之后,直接调用onDestroy()并且不调用任何其他周期函数
Activity生命周期管理之二——Pausing或者Resuming一个Activity
分类:Android2013-01-13 08:14238人阅读评论(0)收藏举报
1.
app使用期间,前台Activity经常被其他的可视组件遮挡,进入paused状态,例如一个对话框弹出时,只要Activity部分可见,但没获得焦点,就处在paused状态
然而,一旦Activity完全不可见,就处在stopped状态
当Activity进入paused状态时,系统调用onPause()方法,其中你可以停止一些任务,或者保存一些数据防止用户其后又退出,如果用户又返回,可以调用onResume()方法脱离paused状态
Note:当Activity接到一个onPause()调用时,可能预示着用户是暂时离开,还会回来,也通常是用户离开时的第一个提示
Pause你的Activity
当Activity接到一个onPause()调用,技术上意味着Activity部分可见,但通常表示用户离开这个Activity,即将进入stopped状态,在onPause()中,通常要做一下事情:
· 停止动画或者其他正在进行的耗费CPU的动作
· 提交未保存的变化,但是只有在用户认为数据应该被保存的时候,例如邮件的草稿
· 释放系统资源,例如broadcast receivers,传感器句柄(例如GPS),或者其他影响电池电量而用户有不用的资源
例如,使用照相机,在onPause()中就可以关掉
[java]view plaincopyprint?
1. @Override
2. publicvoidonPause(){
3. super.onPause();//Alwayscallthesuperclassmethodfirst
4.
5. //ReleasetheCamerabecausewedon'tneeditwhenpaused
6. //andotheractivitiesmightneedtouseit.
7. if(mCamera!=null){
8. mCamera.release()
9. mCamera=null;
10. }
11. }
@Override
public void onPause() {
super.onPause(); // Always call the superclass method first
// Release the Camera because we don't need it when paused
// and other activities might need to use it.
if (mCamera != null) {
mCamera.release()
mCamera = null;
}
}
通常,不应该在onPause()中关闭CPU敏感的资源,像database
connection,会延缓Activity之间的转换,他们最好在onStop()中实现
如果Activity将要进入Stopped状态,在onPause()中就要相对简单的完成操作以使用户能尽快转到下一个Activity,免得影响用户体验
Note: Activity处于paused状态时,Activity的实例还在内存中存在,回到Resumed状态时不需要重新初始化
Resume你的Activity
从paused状态到resumed状态调用onResume()
只要Activity到前台就要调用onResume()方法,包括第一次创建Activity,所以在onRe()方法中要初始化onPause()中释放的组件和其他每次进入resumed状态要实现的动作,例如动画或者只有在获得用户焦点才需要初始化的组件
例如,下面的例子初始化在onPause()中释放的Carema
[java]view plaincopyprint?
1. @Override
2. publicvoidonResume(){
3. super.onResume();//Alwayscallthesuperclassmethodfirst
4.
5. //GettheCamerainstanceastheactivityachievesfulluserfocus
6. if(mCamera==null){
7. initializeCamera();//Localmethodtohandlecamerainit
8. }
9. }
Activity生命周期管理之三——Stopping或者Restarting一个Activity
分类:Android2013-01-14 08:441204人阅读评论(16)收藏举报
适当stop和restart你的Activity对于确保用户的数据没有丢失是很重要的,下面是几个需要stop和restart一个Activity的情况:
· 用户打开最近使用窗口并且切换到其他app,这个Activity被stop,如果用户点击app icon或者从最近使用里返回app,Activity restart
· 从当前Activity打开另一个Activity,当前Activity在另一个Activity被创建时stop,当用户点返回键时,Activity restart
· 用户接电话时
与paused状态不同,stopped的状态下Activity完全不可见,用户焦点完全在另一个Activity或另一个App的Activity
Note:因为系统会在内存中保持Activity实例,所以一般app不用实现onStop或者onRestart方法,甚至onStart方法,因为大多app比较简单,可能只实现onPause方法处理一些资源或者数据即可
Stop你的Activity
当接收到onStop方法调用时,Activity不再可见,应该释放几乎所有不需要使用的资源,一旦Activity stop,如果系统需要回收系统能存,可能销毁实例,极端情况下,系统可能连onDestroy都不调用而直接杀掉进程,所以使用onStop方法处理会导致内存泄露的资源非常重要
即使onPause在onStop之前调用,也应该在onStop中处理更复杂,更耗CPU的操作,像写入数据库等
例如,下面例子像持久存储写入一个草稿
[java]view plaincopyprint?
1. @Override
2. protectedvoidonStop(){
3. super.onStop();//Alwayscallthesuperclassmethodfirst
4.
5. //Savethenote'scurrentdraft,becausetheactivityisstopping
6. //andwewanttobesurethecurrentnoteprogressisn'tlost.
7. ContentValuesvalues=newContentValues();
8. values.put(NotePad.Notes.COLUMN_NAME_NOTE,getCurrentNoteText());
9. values.put(NotePad.Notes.COLUMN_NAME_TITLE,getCurrentNoteTitle());
10.
11. getContentResolver().update(
12. mUri,//TheURIforthenotetoupdate.
13. values,//Themapofcolumnnamesandnewvaluestoapplytothem.
14. null,//NoSELECTcriteriaareused.
15. null//NoWHEREcolumnsareused.
16. );
17. }
@Override
protected void onStop() {
super.onStop(); // Always call the superclass method first
// Save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
Activity处在stopped状态时,Activity对象会保持在内存中,不需要重新初始化resumed状态之前初始化的组件,系统也会跟踪布局中View的状态,所以如果在EditText中有输入也不必保存
Note:即使系统在stopped状态下destroy你的Activity,View的状态仍然被保存在一个Bundle中,当用户再次回到这个Activity事例时还会存在
Start/Restart你的Activity
当Activity从stopped状态到前台来,接到onRestart方法调用,系统也会调用onStart方法,因为每次Activity变得可见时系统都会调用onStart方法,无论创建还是restart,onRestart方法只是在stopped状态resume时才调用,所以可以在在其中执行一些特殊的恢复操作,例如用户长时间离开后,在onStart方法中确保系统状态是否可以是再好不过的了
[java]view plaincopyprint?
1. @Override
2. protectedvoidonStart(){
3. super.onStart();//Alwayscallthesuperclassmethodfirst
4.
5. //Theactivityiseitherbeingrestartedorstartedforthefirsttime
6. //sothisiswhereweshouldmakesurethatGPSisenabled
7. LocationManagerlocationManager=
8. (LocationManager)getSystemService(Context.LOCATION_SERVICE);
9. booleangpsEnabled=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
10.
11. if(!gpsEnabled){
12. //CreateadialogherethatrequeststheusertoenableGPS,anduseanintent
13. //withtheandroid.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGSaction
14. //totaketheusertotheSettingsscreentoenableGPSwhentheyclick"OK"
15. }
16. }
17.
18. @Override
19. protectedvoidonRestart(){
20. super.onRestart();//Alwayscallthesuperclassmethodfirst
21.
22. //Activitybeingrestartedfromstoppedstate
23. }
@Override
protected void onStart() {
super.onStart(); // Always call the superclass method first
// The activity is either being restarted or started for the first time
// so this is where we should make sure that GPS is enabled
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
// Create a dialog here that requests the user to enable GPS, and use an intent
// with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
// to take the user to the Settings screen to enable GPS when they click "OK"
}
}
@Override
protected void onRestart() {
super.onRestart(); // Always call the superclass method first
// Activity being restarted from stopped state
}
因为多数资源在onStop方法中释放,所以一般不用实现onDestroy方法,但也要确保所有可能导致内存泄露的资源已经被释放