Android - setOnClickListener与OnClickListener与View.OnClickListener的区别

45

根据我的理解,当我创建一个监听点击事件的按钮对象时,需要执行以下操作:

  1. 创建按钮对象
  2. 使用 OnClickListner 使其监听用户的点击
  3. 使用 onClick 在用户点击按钮后执行操作

现在,

  • setOnClickListener 在上述逻辑中扮演什么角色?
  • 哪个方法实际上监听按钮的点击事件?
  • setOnClickListener
  • OnClickListener
  • View.OnClickListener
  • 这三者有什么区别?

以下是我在Android开发文档中找到的内容:

//The example below shows how to register an on-click listener for a Button.

// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(mCorkyListener);
    ...
}

你可能会发现将OnClickListener作为Activity的一部分实现更加方便。这样可以避免额外的类加载和对象分配。例如:

public class ExampleActivity extends Activity implements OnClickListener {
    protected void onCreate(Bundle savedValues) {
        ...
         Button button = (Button)findViewById(R.id.corky);
         button.setOnClickListener(this);
    }

    // Implement the OnClickListener callback
    public void onClick(View v) {
      // do something when the button is clicked
    }
}
5个回答

73
假设我们有三个按钮,例如:
public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        // Capture our button from layout
        Button button = (Button)findViewById(R.id.corky);
        Button button2 = (Button)findViewById(R.id.corky2);
        Button button3 = (Button)findViewById(R.id.corky3);
        // Register the onClick listener with the implementation above
        button.setOnClickListener(mCorkyListener);
        button2.setOnClickListener(mCorkyListener);
        button3.setOnClickListener(mCorkyListener);

    }

    // Create an anonymous implementation of OnClickListener
    private View.OnClickListener mCorkyListener = new View.OnClickListener() {
        public void onClick(View v) {
            // do something when the button is clicked 
            // Yes we will handle click here but which button clicked??? We don't know

        }
    };

}

那么我们要做什么呢?
public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        // Capture our button from layout
        Button button = (Button)findViewById(R.id.corky);
        Button button2 = (Button)findViewById(R.id.corky2);
        Button button3 = (Button)findViewById(R.id.corky3);
        // Register the onClick listener with the implementation above
        button.setOnClickListener(mCorkyListener);
        button2.setOnClickListener(mCorkyListener);
        button3.setOnClickListener(mCorkyListener);

    }

    // Create an anonymous implementation of OnClickListener
    private View.OnClickListener mCorkyListener = new View.OnClickListener() {
        public void onClick(View v) {
            // do something when the button is clicked
            // Yes we will handle click here but which button clicked??? We don't know

            // So we will make
            switch (v.getId() /*to get clicked view id**/) {
                case R.id.corky:

                    // do something when the corky is clicked

                    break;
                case R.id.corky2:

                    // do something when the corky2 is clicked

                    break;
                case R.id.corky3:

                    // do something when the corky3 is clicked

                    break;
                default:
                    break;
            }
        }
    };

}

或者我们可以这样做:
public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        // Capture our button from layout
        Button button = (Button)findViewById(R.id.corky);
        Button button2 = (Button)findViewById(R.id.corky2);
        Button button3 = (Button)findViewById(R.id.corky3);
        // Register the onClick listener with the implementation above
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // do something when the corky is clicked
            }
        });
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // do something when the corky2 is clicked
            }
        });
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // do something when the corky3 is clicked
            }
        });

    }

}

或者我们可以实现View.OnClickListener,我认为这是最好的方法:

public class MainActivity extends ActionBarActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        // Capture our button from layout
        Button button = (Button)findViewById(R.id.corky);
        Button button2 = (Button)findViewById(R.id.corky2);
        Button button3 = (Button)findViewById(R.id.corky3);
        // Register the onClick listener with the implementation above
        button.setOnClickListener(this);
        button2.setOnClickListener(this);
        button3.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        // do something when the button is clicked
        // Yes we will handle click here but which button clicked??? We don't know

        // So we will make
        switch (v.getId() /*to get clicked view id**/) {
            case R.id.corky:

                // do something when the corky is clicked

                break;
            case R.id.corky2:

                // do something when the corky2 is clicked

                break;
            case R.id.corky3:

                // do something when the corky3 is clicked

                break;
            default:
                break;
        }
    }
}

最终这里没有真正的区别,只是“比其他更好”


第二种方式是否比其他方式表现稍好?在第一种和第三种方式中,需要首先确定点击了哪个视图,然后再执行操作,而在第二种方式中,则可以直接跳转到操作。很好奇其他人会说些什么,因为我并不完全确定我的逻辑是否正确。 - CodyEngel
1
@HuskyHuskie。要知道何时应关注性能,何时不必关注。问问自己:用户点击有多频繁?用户点击时什么响应时间是可接受的?我的目标设备执行每秒多少百万个Java指令?确认查找视图所需的少量指令是否重要?此外,考虑处理点击所需的工作量。在操作系统中计算代码,可能会执行数千次、数万次甚至数十万次Java指令。我想你知道这会导致什么问题…… - ToolmakerSteve
能否同时使用它们两个,我的意思是不仅仅是“implements View.OnClickListener”,还包括“SetOnClickListener”? - Davoud Badamchi
@Patze 是的,你可以在不同的视图中同时使用它们。 - Ibrahim Disouki
1
很棒的例子。但我有一个问题...在这些例子中,当我使用xml中的android:onClick(function)来捕获按钮的点击事件时,应该在什么情况下使用它?这只是第四种捕获点击的方式吗? - M K
就风格而言,我更喜欢第二种(类似JS的风格),讨厌那些开关。对我来说,这种(JS)方法比开关结构更快,但在使用三个对象而不是一个对象方面,它将使用更多内存。 - Andrii Bogachenko

26
逻辑很简单。 setOnClickListener 属于步骤2。
  1. 创建按钮。
  2. 像示例中那样创建一个 OnClickListener 实例并覆盖 onClick 方法。
  3. 在您的片段 / 活动的 onCreate 方法中,使用 btn.setOnClickListener(myOnClickListener); 将该 OnClickListener 分配给该按钮。
  4. 当用户单击按钮时,调用分配的 OnClickListeneronClick 函数。

*如果您导入了 android.view.View;,则使用 View.OnClickListener。如果您导入了 android.view.View.*;import android.view.View.OnClickListener;,则根据我的理解使用 OnClickListener

另一种方法是让您的活动/片段从 OnClickListener 继承。这样,您将您的片段/活动分配为按钮的侦听器,并将 onClick 实现为成员函数。


10
请注意,为了简单起见,我仅引用了第一个代码片段,即:
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

protected void onCreate(Bundle savedValues) {
    ...
    // Capture our button from layout
    Button button = (Button)findViewById(R.id.corky);
    // Register the onClick listener with the implementation above
    button.setOnClickListener(mCorkyListener);
    ...
}

setOnClickListener(View.OnClickListener l)是View类的公共方法。Button类扩展了View类,因此可以调用setOnClickListener(View.OnClickListener l)方法。

setOnClickListener方法注册一个回调函数,当视图(在您的情况下是按钮)被点击时调用。这回答了您的前两个问题:

1. setOnClickListener在上述逻辑中起到什么作用?

答:它在按钮点击时注册回调函数。(在下一段中详细解释)

2. 哪一个实际上监听按钮点击事件?

答:实际监听按钮点击事件的是setOnClickListener方法。

当我说它注册一个回调函数以便调用时,我的意思是会执行输入为该方法的参数View.OnClickListener l。在您的情况下,它将是button.setOnClickListener(mCorkyListener);中提到的mCorkyListener,然后执行其中提到的onClick(View v)方法。

// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
    public void onClick(View v) {
      // do something when the button is clicked
    }
};

进一步说,OnClickListener 是一个接口定义,用于在视图(在你的情况下是按钮)被点击时调用回调。简单地说,当你点击那个按钮时,由于它是 OnClickListener 的实现,所以 mCorkyListener 中的方法将被执行。但是,OnClickListener 只有一个方法,即 OnClick(View v)。因此,需要在点击按钮时执行的任何操作都必须编码在这个方法中。

现在你知道了 setOnClickListenerOnClickListener 的含义,我相信你自己能够区分两者之间的不同。第三个术语 View.OnClickListener 实际上就是 OnClickListener。你在前面加上 View. 的唯一原因是程序开头的 import 语句的差异。如果你只有这样一个导入语句: import android.view.View;,那么你必须使用 View.OnClickListener。如果你提到以下任意一个导入语句: import android.view.View.*; 或者 import android.view.View.OnClickListener;,你就可以省略 View.,直接使用 OnClickListener


6

View是所有小部件的超类,OnClickListener接口属于这个类。所有小部件都继承了它。View.OnClickListener与OnClickListener相同。要实现您想要的按钮操作,您需要重写此监听器的onClick(View view)方法。

要告诉Android监听小部件的点击事件,您需要执行以下操作:

widget.setOnClickListener(this); // If the containing class implements the interface
// Or you can do the following to set it for each widget individually
widget.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        // Do something here
    }
});

在 onClick() 方法中传递的 “View” 参数只是让 Android 知道某个视图已被点击。它可以是一个按钮、文本视图或其他视图。您可以为每个小部件设置 OnClickListener,或者仅使包含所有这些小部件的类实现接口。在这种情况下,您将为所有小部件拥有一个公共的 onClick() 方法,您只需检查传入该方法的视图的 id,并将其与您想要的每个元素的 id 进行匹配,然后为该元素执行操作。

3
  1. 首先,View.OnClickListenerOnClickListener没有区别。如果你直接使用View.OnClickListener,那么就不需要写-

    import android.view.View.OnClickListener

  2. 通过setOnclickListener()方法将一个OnClickListener实例(例如命名为myListener的对象)设置为视图的监听器。当触发click事件时,myListener会被通知并调用它的onClick(View view)方法。这就是我们执行自己任务的地方。 希望能对你有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接