从Java到Android开发: 监听器Listener接口

1. 再谈接口

1.1 定义接口

定义接口的一般格式如下:

[public] interface 接口名 [extends 父接口名]{
	[public] [static] [final] 数据类型 常量名 = 常量;//常量声明
	[public] [abstract] 返回类型 方法名(参数列表);//抽象方法声明
}
  • 接口可以抽象出重要的行为标准,该行为标准用抽象方法来表示。接口中只有常量和抽象方法;
  • 接口中的变量自动都是publicstaticfinal,可以省略 ;
  • 接口中的方法自动为public abstract,可以省略;
  • 接口编译后也产生class文件;
  • 接口中没有构造方法。 也就不能通过new构建接口的对象,只能像抽象类一样标示数据类型;
  • 接口也具有继承性,可以继承父接口的所有属性和方法。

实现接口类的的格式形如:

class Test implements Printable,Addable{
	@Override
	void getValue(int x){
		//...
	}
} 

1.2 接口回调

可以把实现某一接口的类创建的对象的赋值给该接口声明的接口变量中,即接口变量存放实现该接口的类的对象的引用,从而接口变量就可以回调类实现的接口方法。

接口回调是实现多态的关键技术。若干个不同的类通过实现同一接口,从而具有相同名称的方法,但方法的具体内容 (实现) 不同。

例如:

Com com;//声明接口对象, Com是一接口
ImpleCom obj= new ImpleCom();//实现接口的类对象 
com = obj; //接口回调

1.3 将接口作为参数

如果一个方法的参数是接口类型,则可以将任何实现该接口的类的实例的引用传递给该接口参数,那么接口参数就可以回调类实现的接口方法。例如,在1.2中若有方法的参数是Com接口类型,则调用该方法时,可将obj作为参数。

再例如,对于View类的方法public void setOnClickListener(OnClickListener l),其接受一个OnClickListener接口类型的参数l,于是调用该方法时,可将某OnClickListener的实现类对象作为参数。下面代码中,由于MainActivity通过实现onClick()方法实现了OnClickListener接口,于是该类的实例对象this可作为setOnClickListener(OnClickListener l)的参数。

1.4 匿名类

  • Java 中可以实现一个类中包含另外一个类,且不需要提供任何的类名直接实例化。匿名类没有名字,以不可能用匿名类声明对象,但可以直接用匿名类创建一个对象。不能被第二次使用,只能在创建时用 new 语句来声明它们。匿名类可以继承类的方法也可以重写类的方法;不可以声明static成员变量和static方法。

  • 匿名类的主要用途就是向方法的参数传值,并且可以使代码更加简洁。

  • 匿名类的应用主要体现在与类有关的匿名类与接口有关的匿名类

与类有关的匿名类:

class AnoTest{
	int num=10;
	void Show() {
		System.out.println("Function in super,num="+num+";Calculate()="+Calculate());
	}
	int Calculate() {
		return num*num;
	}
}
public class AnoClass {
	public static void main(String[] args) {
		AnoTest ano1 = new AnoTest();
		AnoTest ano2 = new AnoTest(){
			//匿名类可以继承父类的方法,也可以重写父类的方法
			void Show() {
				num=20;
				System.out.println("Function in extends,num="+num+";Calculate()="+Calculate());
			}
		};
		ano1.Show();
		ano2.Show();
		System.out.println(ano1.getClass());
		System.out.println(ano2.getClass());
	}
}
//Function in super,num=10;Calculate()=100
//Function in extends,num=20;Calculate()=400
//class demo.AnoTest
//class demo.AnoClass$1

1.5 接口的理解

Collection工具类的各个接口
在这里插入图片描述

2. Android事件的监听

2.1 事件监听机制

事件监听机制中由事件源,事件,事件监听器三类对象组成。
处理流程如下:

  1. 为某个事件源(组件)设置一个监听器,用于监听用户操作
  2. 用户的操作,触发了事件源的监听器
  3. 生成了对应的事件对象
  4. 将这个事件源对象作为参数传给事件监听器
  5. 事件监听器对事件对象进行判断,执行对应的事件处理器(对应事件的处理方法)

2.2 监听器接口

对于一个监听器,其必须满足处理该事件的能力,即实现对应接口。例如,单击事件(Click)的监听器必须实现OnClickListener接口,该接口规定了监听器必须提供onClick()方法及方法的规格。于是,在View类的各个组件的注册监听器方法中(如setOnClickListener()),传递的参数均为实现对应接口的类对象。

3. 监听器的几种注册方法

  1. 使用内部匿名类,形如button.setOnClickListener(new OnClickListener(){...});,在匿名类中实现onClick()方法;
  2. 将活动作为事件监听器,Activity实现接口,形如public class MainActivity extends Activity implements OnClickListener{...},在MainActivity中定义onClick()方法;
  3. 直接绑定到标签,在活动中定义一个事件处理方法,然后在对应xml布局文件中为组件设置触发事件:如设置属性:onclick = "myclick",表示将该组件的单击事件的监听器注册为myclick()方法。(不具有普适性,只有单击Click事件有对应属性,如长按LongClick则没有。)

4. 实例: 为Button组件实现并注册监听器

本实例中,对于4个Button组件,分别使用3.中的3中方法注册监听器。

4.1 java文件: MainActivity.java

public class MainActivity extends AppCompatActivity implements OnClickListener {
    Button btn1, btn2, btn3, btn4;
    EditText editTxt1, editTxt2;
    TextView txt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn1 = findViewById(R.id.button);
        btn2 = findViewById(R.id.button2);
        btn3 = findViewById(R.id.button3);
        btn4 = findViewById(R.id.button4);
        editTxt1 = findViewById(R.id.editTextNumber);
        editTxt2 = findViewById(R.id.editTextNumber2);
        txt = findViewById(R.id.textView);

        btn1.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int a = Integer.parseInt(editTxt1.getText().toString());
                int b = Integer.parseInt(editTxt2.getText().toString());
                int ans = a * b;
                txt.setText("Ans(Multi): " + ans);
            }
        });
        btn2.setOnClickListener(this);
        btn3.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int a = Integer.parseInt(editTxt1.getText().toString());
        int b = Integer.parseInt(editTxt2.getText().toString());
        int ans;
        switch (v.getId()) {
            case R.id.button2:
                ans = a + b;
                txt.setText("Ans(Add): " + ans);
                break;
            case R.id.button3:
                ans = a - b;
                txt.setText("Ans(Sub): " + ans);
                break;
            default:
                break;
        }
    }

    public void myButtonClick(View v) {
        int a = Integer.parseInt(editTxt1.getText().toString());
        int b = Integer.parseInt(editTxt2.getText().toString());
        String ans = "Ans(Link): " + a + b;
        txt.setText(ans);
    }
}

4.2 布局文件: activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.458"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.46" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.208"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.631" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.725"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.631" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.208"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.767" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="myButtonClick"
        android:text="Button4"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.725"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.767" />

    <EditText
        android:id="@+id/editTextNumber"
        android:layout_width="132dp"
        android:layout_height="56dp"
        android:ems="10"
        android:hint="Num1..."
        android:inputType="number"
        android:minHeight="48dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.113"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.22" />

    <EditText
        android:id="@+id/editTextNumber2"
        android:layout_width="132dp"
        android:layout_height="56dp"
        android:ems="10"
        android:hint="Num2..."
        android:inputType="number"
        android:minHeight="48dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.785"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.22" />

</androidx.constraintlayout.widget.ConstraintLayout>

参考链接:
[1]匿名类 - https://www.cnblogs.com/progor/p/8644634.html
[2]匿名类 - https://www.runoob.com/java/java-anonymous-class.html
[3]将接口作为参数 - https://blog.csdn.net/blackmanren/article/details/9252437
[4]将接口作为参数 - https://www.jianshu.com/p/9acc1ff3a5b6
[5]事件监听 - https://www.runoob.com/w3cnote/android-tutorial-listen-event-handle.html
[6]注册监听器三种方法 - https://blog.csdn.net/qq_43175022/article/details/106562090
[7]注册监听器三种方法2 - https://blog.csdn.net/rongwenbin/article/details/90767720

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值