Best Way to Implement View.Onclicklistener in Android

Best way to implement View.OnClickListener in Android

First, there is no best practice defined by Android regarding registering click listeners. It totally depends on your use case.

Implementing the View.OnClickListener interface to Activity is the way to go. As Android strongly recommends interface implementation over and over again whether it is an Activity or Fragment.

Now as you described :

public class ActivityMain extends Activity implements View.OnClickListener
{
private class ClickListener implements View.OnClickListener
{
@Override
public void onClick(View view)
{
switch (view.getId())
{
//handle multiple view click events
}
}
}
}

This is your approach. Now it is your way of implementation and there is nothing wrong with this if you are not concerned with memory overhead. But what's the benefit of creating the inner class and implementing the View.OnClickListener if you can simply implement that in the main class which can also lead to the code clarity and simplicity that you need.

So it just a discussion rather getting the best possible solution of implementing the View.OnClickListener because if you go with the practical point of everyone, you will go for a solution which is simple and memory efficient.

So I would prefer the conventional way. It keeps things simple and efficient. Check the code below:

@Override
public void onClick(View view)
{
switch (view.getId())
{
//handle multiple view click events
}
}

P.S : Your approach will definitely increase lines of code :P ;)

How to implement OnClickListener on Android

Try this:

public class MainActivity extends Activity  {

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

if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}

//Button button = (Button)findViewById(R.id.try_button);
//button.setOnClickListener(this);
}

/**
public void onClick(View v) {

}
*/

@Override
public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment implements OnClickListener {

public PlaceholderFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);

Button button = (Button) rootView.findViewById(R.id.try_button);
button.setOnClickListener(this);

return rootView;
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getActivity(), "I'm clicked!", Toast.LENGTH_SHORT).show();
}

}
}

How do I properly implement View.OnClickListener and use it with a TextView?

The root of the issue is with your activity declaration and there are two ways to deal with it.

  • Let your activity implement the View.onClickListener and you pass the activity to the textview's setOnClickListener
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
...
TextView title = findViewById(R.id.title);
title.setOnClickListener(this);

TextView title2 = findViewById(R.id.textview2);
title2.setOnClickListener(this);

// implement the onClick method in your MainActivity class
@Override
public void onClick(View view) {
switch(view.getId()){
case R.id.TextView1 : //logic for textview1
break;

case R.id.TextView2: // logic for textview2
break;
}
}
}
  • Modify your Activity function declaration and create a a new instance of View.OnClickListener in setOnClickListener method.
public class MainActivity extends AppCompatActivity {
...
TextView title = findViewById(R.id.title);
title.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
...
}
});
}

Deciding when to implement OnClickListener in each view, or implementing activity to View.OnClickListener?

There is no best practice defined by Android regarding registering click listeners. It totally depends on your use case.

Implementing the View.OnClickListener interface to Activity is the way to go. As Android strongly recommends interface implementation over and over again whether it is an Activity or Fragment.

Android onClickListener implementation best practices

Here we use so called callback pattern.

public class Button {
private Callback callback;

public Button(Callback callback) {
this.callback = callback;
}

public void update() {
// Check if clicked..
callback.onClick(this);
}

public interface Callback {
public void onClick(Button Button);
}
}

Button b = new Button(new Callback() {
@Override
public void onClick(Button b) {
System.out.println("Clicked");
}
});

In our case onClick handler implements the interface View.OnClickListener.

Key points:

  • consistency with activity/fragment;
  • access to the members of activity/fragment;
  • readability;
  • @Michael Krause showed one more good point about memory leaks;

1) Attribute in the XML file can be used only for activity, as @Karakuri mentioned it uses reflection which is slow.

2) Anonymous inner class has special rules for access to the members of enclosing class (check [1], [2]). There are some situations when memory leaks can happen (ex. threading with AsyncTask, Handlers).

3) Here you have a full access to the members of enclosing class.

4) Is a variation of 3d.

Readability depends on your handler size, small logic can be ok to inline, but for larger blocks of code consider 3d and 4th.

best implementation of onclick()

In that case, I might add implements View.OnClickListener to the activity class, and then make a single onClick that looks like:

@Override
public void onClick(View v){
switch(v.getId()){
case R.id.button1:
// handle button1 click
break;
case R.id.button2:
// handle button3 click
break;
case R.id.button3:
// handle button3 click
break;
// etc...
}
}

This only really makes sense if the actions of all those buttons are somehow related, and if they are then it can significantly reduce code duplication. You would still have to do view.setOnClickListener(this) for each one, too.

Alternatively, if you want you can remove the implements View.OnClickListener and the @Override and simply register your method in the XML, like Kevin said. That would allow you to have multiple of these "grouped" click listeners.

what is better way to organize onclicklistener?

The most obvious example of alternative approaches to solving a single problem seems to be the various ways you can handle button clicks. As far as I know, there are four different ways to add listeners for handling button clicks. If you know of other ways, please post a comment and share them with us.

Xml

  <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:text="Inner Class (btn1)" android:id="@+id/Button01"
android:layout_width="fill_parent" android:layout_height="wrap_content">
</Button>
<Button android:text="Anonymous Inner Class (btn2)"
android:id="@+id/Button02" android:layout_width="fill_parent"
android:layout_height="wrap_content">
</Button>
<Button android:text="Implementing an Interface (btn3)"
android:id="@+id/Button03" android:layout_width="fill_parent"
android:layout_height="wrap_content">
</Button>
<Button android:text="Calling From XML Layout (btn4)"
android:id="@+id/Button04" android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="btn4Listener">
</Button>
</LinearLayout>

in MainActivity

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class Main extends Activity implements View.OnClickListener {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//method 1 - uses an inner class named btn1Listener...
Button btn1 = (Button)findViewById(R.id.Button01);
btn1.setOnClickListener(btn1Listener);

//method 2 - use an anonymous inner class as a listener...
Button btn2 = (Button)findViewById(R.id.Button02);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showToastMessage("You clicked btn2 - uses an anonymouse inner class");
}
});

//method 3 - note that this class implements
//the View.OnClickListener interface
//which means that we must implement the onClick()
//method (which you'll find below)..
Button btn3 = (Button)findViewById(R.id.Button03);
btn3.setOnClickListener(this);
//method 4 - look at the method btn4Listener() below
}

//here's the inner class used as a listener for btn1...

private View.OnClickListener btn1Listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
showToastMessage("You clicked btn1 - uses an inner class named btn1Listener");
}
};

//here's a method that you must have when your activity implements the
//View.OnClickListener interface...
@Override
public void onClick(View v) {
showToastMessage("you clicked on a btn3, which uses this Activity as the listener");
}
//here's the handler for btn4 (declared in the xml layout file)...
//note: this method only works with android 2.1 (api level 7), it must be public and
//must take a single parameter which is a View

public void btn4Listener(View v) {
showToastMessage("You clicked btn4 - listener was set up in the XML layout");
}
private void showToastMessage(String msg){
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.show();
}
}

Cannot Implement View.onClickListener in Adapter class

You need to implement onClick method if you implement View.OnClickListener but in your case you set listener like below

cv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// Toast.makeText(view.getContext(), "ithu thaan mudiyum", Toast.LENGTH_SHORT).show();
if(listener!=null)
listener.onItemClick(personName.getText().toString(),personAge.getText().toString());
}
});

therefore you need to either delete implements View.OnClickListeneror override its onClick() method like below in your view holder class

@Override
public void onClick(View v) {

}


Related Topics



Leave a reply



Submit