一、使用内部类作为事件监听器
和上面的匿名内部类不同,使用内部类可以在当前类中复用该监听器类;因为监听器类是外部类的内部类,所以可以自由访问外部类的所有界面组件,这也是内部类的两个优势。
接下来通过一个简单的示例程序来学习Android使用内部类作为事件监听器。
继续使用WidgetSample工程,在app/main/res/layout/目录下创建event_inner_class_layout.xml文件,在其中填充如下代码片段:
<?
xml version
“1.0”
encoding
“utf-8”
?>
<
RelativeLayout
xmlns
:
android
“http://schemas.android.com/apk/res/android”
android
:
layout_width
“match_parent”
android
:
layout_height
“match_parent”
<
Button
android
:
id
“@+id/button”
android
:
layout_width
“match_parent”
android
:
layout_height
“wrap_content”
android
:
text
“使用内部类监听事件”
/>
</
RelativeLayout
然后在java包下创建EventListenerInnerClassActivity.java文件,加载上面新建的布局文件,使用内部类监听事件,需要修改一下界面交互代码,具体代码如下:
package com
.
jinyu
.
cqkxzsxy
.
android
.
widgetsample
;
import
android
.
os
.
Bundle
;
import
android
.
support
.
v7
.
app
.
AppCompatActivity
;
import
android
.
view
.
View
;
import
android
.
widget
.
Button
;
import
android
.
widget
.
Toast
;
public
class
EventListenerInnerClassActivity
extends
AppCompatActivity
{
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
event_inner_class_layout
);
// 获取界面组件
Button
button
(
Button
)
findViewById
(
R
.
id
.
button
);
// 使用内部类的实例作为事件监听器
button
.
setOnClickListener
(
new
BtnClickListener
());
}
// 定义一个内部类,实现View.OnClickListener接口,并重写onClick()方法
class
BtnClickListener
implements
View
.
OnClickListener
{
@Override
public
void
onClick
(
View
view
)
{
// 实现事件处理
Toast
.
makeText
(
EventListenerInnerClassActivity
.
this
,
“收到点击事件”
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
}
修改AndroidManifest.xml文件中启动的Activity为EventListenerInnerClassActivity,具体代码如下:
<?
xml version
“1.0”
encoding
“utf-8”
?>
<
manifest xmlns
:
android
“http://schemas.android.com/apk/res/android”
package
=
“com.jinyu.cqkxzsxy.android.widgetsample”
<
application
android
:
allowBackup
“true”
android
:
icon
“@mipmap/ic_launcher”
android
:
label
“@string/app_name”
android
:
roundIcon
“@mipmap/ic_launcher_round”
android
:
supportsRtl
“true”
android
:
theme
“@style/AppTheme”
<
activity android
:
name
“.EventListenerInnerClassActivity”
<
intent
filter
<
action android
:
name
“android.intent.action.MAIN”
/>
<
category android
:
name
“android.intent.category.LAUNCHER”
/>
</
intent
filter
</
activity
</
application
</
manifest
运行程序,点击按钮,可以看到下图所示界面效果。
二、使用外部类作为事件监听器
使用外部类定义事件监听器类的形式比较少见,主要因为如下两个原因。
事件监听器通常属于特定的GUI界面,定义成外部类不利于提高程序的内聚性。
外部类形式的事件监听器不能自由访问创建GUI界面的类中的组件,编程不够简洁。
但如果某个事件监听器确实需要被多个GUI界面所共享,而且主要是完成某种业务逻辑的实现,则可以考虑使用外部类形式来定义事件监听器类。
接下来通过一个简单的示例程序来学习Android使用外部类作为事件监听器。
继续使用WidgetSample工程,在app/main/res/layout/目录下创建event_outer_class_layout.xml文件,在其中填充如下代码片段:
<?
xml version
“1.0”
encoding
“utf-8”
?>
<
RelativeLayout
xmlns
:
android
“http://schemas.android.com/apk/res/android”
android
:
layout_width
“match_parent”
android
:
layout_height
“match_parent”
<
Button
android
:
id
“@+id/button”
android
:
layout_width
“match_parent”
android
:
layout_height
“wrap_content”
android
:
text
“使用外部类监听事件”
/>
</
RelativeLayout
然后新建一个监听器BtnClickListener类,具体代码如下:
package com
.
jinyu
.
cqkxzsxy
.
android
.
widgetsample
.
listener
;
import
android
.
app
.
Activity
;
import
android
.
view
.
View
;
import
android
.
view
.
View
.
OnClickListener
;
import
android
.
widget
.
Toast
;
/**
-
@创建者 鑫鱻
-
@描述 Android零基础入门到精通系列教程,欢迎关注微信公众ShareExpert
*/
public
class
BtnClickListener
implements
OnClickListener
{
private
Activity
mActivity
null
;
// 构造方法
public
BtnClickListener
(
Activity
act
){
this
.
mActivity
act
;
}
// 实现事件处理方法
@Override
public
void
onClick
(
View
view
)
{
// 实现事件处理
Toast
.
makeText
(
mActivity
,
“收到点击事件”
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
然后在java包下创建EventListenerOuterClassActivity.java文件,加载上面新建的布局文件,使用外部类监听事件,需要修改一下界面交互代码,具体代码如下:
package com
.
jinyu
.
cqkxzsxy
.
android
.
widgetsample
;
import
android
.
os
.
Bundle
;
import
android
.
support
.
v7
.
app
.
AppCompatActivity
;
import
android
.
widget
.
Button
;
import
com
.
jinyu
.
cqkxzsxy
.
android
.
widgetsample
.
listener
.
BtnClickListener
;
public
class
EventListenerOuterClassActivity
extends
AppCompatActivity
{
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
event_outer_class_layout
);
// 获取界面组件
Button
button
(
Button
)
findViewById
(
R
.
id
.
button
);
// 使用外部类的实例作为事件监听器
button
.
setOnClickListener
(
new
BtnClickListener
(
this
));
}
}
修改启动的Activity,然后运行程序,点击按钮,可以看到下图所示界面效果。
实际上不推荐将业务逻辑实现写在事件监听器中,包含业务逻辑的事件监听器将导致程序的显示逻辑和业务逻辑耦合,从而增加程序后期的维护难度。
如果确实有多个事件监听器需要实现相同的业务逻辑功能,则可以考虑使用业务逻辑组件来定义业务逻辑功能,再让事件监听器来调用业务逻辑组件的业务逻辑方法。
三、直接使用Activity作为事件监听器
这种形式使用Activity本身作为监听器类,可以直接在Activity类中定义事件处理器方法,这种形式非常简洁。但是这样存在两个问题。
这种形式可能造成程序结构混乱,Activity的主要职责应该是完成界面初始化工作,但此时还需包含事件处理器方法,从而引起混乱。
如果Activity界面类需要实现监听器接口,让人感觉比较怪异。
接下来通过一个简单的示例程序来学习Android直接使用Activity作为事件监听器。
继续使用WidgetSample工程,在app/main/res/layout/目录下创建event_activity_class_layout.xml文件,在其中填充如下代码片段:
<?
xml version
“1.0”
encoding
“utf-8”
?>
<
RelativeLayout
xmlns
:
android
“http://schemas.android.com/apk/res/android”
android
:
layout_width
“match_parent”
android
:
layout_height
“match_parent”
<
Button
android
:
id
“@+id/button”
android
:
layout_width
“match_parent”
android
:
layout_height
“wrap_content”
android
:
text
“使用Activity作为事件监听器”
/>
</
RelativeLayout
然后在java包下创建EventListenerActivityClassActivity.java文件,加载上面新建的布局文件,为了监听登录按钮的点击事件,在Java代码中为其添加点击事件监听器,具体代码如下:
package com
.
jinyu
.
cqkxzsxy
.
android
.
widgetsample
;
import
android
.
os
.
Bundle
;
import
android
.
support
.
v7
.
app
.
AppCompatActivity
;
import
android
.
view
.
View
;
import
android
.
widget
.
Button
;
import
android
.
widget
.
Toast
;
public
class
EventListenerActivityClassActivity
extends
AppCompatActivity
implements
View
.
OnClickListener
{
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
event_activity_class_layout
);
// 获取界面组件
Button
button
(
Button
)
findViewById
(
R
.
id
.
button
);
// 使用Activity作为事件监听器
button
.
setOnClickListener
(
this
);
}
// 实现事件处理方法
@Override
public
void
onClick
(
View
view
)
{
// 实现事件处理
Toast
.
makeText
(
EventListenerActivityClassActivity
.
this
,
“收到点击事件”
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
修改启动的Activity,然后运行程序,点击按钮,可以看到下图所示界面效果。
四、直接绑定到标签
Android还有一种更简单的绑定事件监听器的方式,那就是直接在界面布局文件中为指定标签绑定事件处理方法。
对于很多Android界面组件标签而言,它们都支持onClick属性,该属性的属性值就是一个形如xxx(View source)方法的方法名。
接下来通过一个简单的示例程序来学习Android直接绑定到标签进行事件处理。
继续使用WidgetSample工程,在app/main/res/layout/目录下创建event_xml_label_layout.xml文件,在其中填充如下代码片段:
<?
xml version
“1.0”
encoding
“utf-8”
?>
<
RelativeLayout
xmlns
:
android
“http://schemas.android.com/apk/res/android”
android
:
layout_width
“match_parent”
android
:
layout_height
“match_parent”
<
Button
android
:
id
“@+id/button”
android
:
layout_width
“match_parent”
android
:
layout_height
“wrap_content”
android
:
onClick
“clickHandler”
android
:
text
“事件监听器直接绑定到标签”
/>
</
RelativeLayout
上面程序中的粗体字代码用于在界面布局文件中为Button按钮绑定一个事件处理方法: clickHandler,这就意味着幵发者需要在该界面布局对应的Activity中定义一个void clickHandler(View source)方法,该方法将会负责处理该按钮上的单击事件。
然后在java包下创建EventListenerXmlLabelActivity.java文件,加载上面新建的布局文件,由于在布局文件绑定点击事件,顾在界面交互代码里面定义事件处理方法即可,具体代码如下:
package com
.
jinyu
.
cqkxzsxy
.
android
.
widgetsample
;
import
android
.
os
.
Bundle
;
import
android
.
support
.
v7
.
app
.
AppCompatActivity
;
import
android
.
view
.
View
;
import
android
.
widget
.
Toast
;
public
class
EventListenerXmlLabelActivity
extends
AppCompatActivity
{
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
super
.
onCreate
(
savedInstanceState
);
setContentView
(
R
.
layout
.
event_xml_label_layout
);
}
/**
* 定义一个事件处理方法
* @param source 事件源
*/
public
void
clickHandler
(
View
source
){
// 实现事件处理
Toast
.
makeText
(
EventListenerXmlLabelActivity
.
this
,
“收到点击事件”
,
Toast
.
LENGTH_SHORT
).
show
();
}
}
上面程序中的粗体字代码定义了一个clickHandler(View source)方法,当程序中的按钮被单击时,该方法将会被激发并处理对应按钮上的单击事件。