Android事件处理详解

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

目录(?)[+]

1.理解生命周期回调函数

2.指定app启动Activity

3.创建一个新实例

4.Destroy一个Activity

Activity的生命周期完全由Android系统进行管理,周期中有几个主要的状态,下面介绍一下

理解生命周期回调函数

下面一张图说的很清晰:

根据app的复杂性,不一定实现所有生命周期函数,但理解他们并知道什么时候该实现是很重要的,实现周期函数要保证一下几点:

· 接电话或转移到另一个app的时候不要产生冲突

· 用户不用时不要消耗可观的系统资源

· 在用户暂时离开时不要丢失用户数据和进展

· 屏幕方向改变时不要丢失用户数据

有三个状态时可以保持的:

Resumed

此状态下,activity在前台,可以和用户交互,也叫运行状态

Paused

此状态下,本activity被另一个前台activity隐藏,这个前台activity是半透明的或只占据部分屏幕,paused状态下activity不接受用户输入,也不执行任何代码

Stopped

此状态下,activity完全不可见,也就是在后台,所有实例对象和成员变量等都被保存,但不执行任何代码

其他状态都是瞬时的,调用onCreate后立即调用onStart后立即调用onResume

这些是基本的周期状态,下面看看一些特殊的生命周期表现

指定app启动Activity

用户触点你的app icon时,系统调用被你声明为launcher activityonCreate()函数,这个activity提供程序用户界面的主入口

可以在Android manifest文件中定义

launcher activity必须以<intent-filter>定义,包含MAIN actionLAUNCHER 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 actionLAUNCHER categoryapp 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()函数何时使用,他们也是很有用的,特别对于经常从PausedStopped状态转换为Resumed状态的activity

Note: onCreate()的参数savedInstanceState后面再说

Destroy一个Activity

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.

2.Pause你的Activity

3.Resume你的Activity

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)收藏举报

目录(?)[+]

1.Stop你的Activity

2.StartRestart你的Activity


适当stoprestart你的Activity对于确保用户的数据没有丢失是很重要的,下面是几个需要stoprestart一个Activity的情况:

· 用户打开最近使用窗口并且切换到其他app,这个Activitystop,如果用户点击app icon或者从最近使用里返回appActivity restart

· 从当前Activity打开另一个Activity,当前Activity在另一个Activity被创建时stop,当用户点返回键时,Activity restart

· 用户接电话时

paused状态不同,stopped的状态下Activity完全不可见,用户焦点完全在另一个Activity或另一个AppActivity

Note:因为系统会在内存中保持Activity实例,所以一般app不用实现onStop或者onRestart方法,甚至onStart方法,因为大多app比较简单,可能只实现onPause方法处理一些资源或者数据即可

Stop你的Activity

当接收到onStop方法调用时,Activity不再可见,应该释放几乎所有不需要使用的资源,一旦Activity stop,如果系统需要回收系统能存,可能销毁实例,极端情况下,系统可能连onDestroy都不调用而直接杀掉进程,所以使用onStop方法处理会导致内存泄露的资源非常重要

即使onPauseonStop之前调用,也应该在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你的ActivityView的状态仍然被保存在一个Bundle中,当用户再次回到这个Activity事例时还会存在

Start/Restart你的Activity

Activitystopped状态到前台来,接到onRestart方法调用,系统也会调用onStart方法,因为每次Activity变得可见时系统都会调用onStart方法,无论创建还是restartonRestart方法只是在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方法,但也要确保所有可能导致内存泄露的资源已经被释放

更多相关文章

  1. Android中的UID和PID意义,及查看方式
  2. Android源码分析之WindowManager.LayoutParams属性更新过程
  3. Android实用视图动画及工具系列之四:多状态CheckBox,可设置大小尺
  4. android中Webview与javascript的交互(互相调用)
  5. Android(安卓)App 启动流程梳理(基于 Android(安卓)10)
  6. Android菜鸟的成长笔记(14)—— Android中的状态保存探究(上)
  7. Android(安卓)APP设计加载使用gif动图需要注意的一般性问题
  8. Android的生命周期
  9. 在Android中监控来电和去电

随机推荐

  1. Android(安卓)-- CursorAdapter
  2. 收集的几篇 Android(安卓)刷机 文章
  3. tiny210 android 移植过程中的几个问题
  4. Android——本息计算器
  5. Android(安卓)APP更新_后台下载、自动安
  6. Android初学笔记——五:数据存储
  7. 2.2 android中的多进程机制
  8. Android(安卓)显示手机电池的当前电量
  9. android分区大小的修改说明(RK)
  10. android 动态设置margin