Best way to implement View.OnClickListener in android

后端 未结 14 2292
盖世英雄少女心
盖世英雄少女心 2020-11-27 05:25

Suppose we have an Activity with a lot of views on which OnClickListener is to be registered.

The most common way to implement this is to let the Activi

相关标签:
14条回答
  • 2020-11-27 06:07

    For this particular case I'd say that maintain a single instance of a OnClickListener is the best approach for you. You will have a "Has-a" relationship and won't need to create several instances since you are handling the behavior using the view id in the onClick(View view) callback.

    public class ActivityMain extends Activity implements View.OnClickListener {
    
        private View.OnClickListener mClickListener = new View.OnClickListener() {   
            @Override
            public void onClick(View view) {
                switch (view.getId()) {
                    //handle multiple view click events
                }
            }
        };
    
    }
    
    0 讨论(0)
  • 2020-11-27 06:11

    First of all lets get the basics clear here..

    By implementing an Interface, your class doesn't become that.. like you said:

    "Our Activity-Subclass "Is-a" ClickListener, which ain't completely true."

    Your class can only have "Is-a" relationship if it extends, in this case an Activity. Implementing an interface means that it can behave like what interface has set its contract.

    An Example:

    class Peter extends Human .. means Peter is a Human..

    class Peter can also implement programmer, musician, husband etc means Peter can behave as the above.

    As for best practice, you could make an entirely separate class which implements OnClickListener like this:

    class MyListener implements View.OnClickListener{
    
      @Override
    public void onClick(View view) {
            // do whatever you want here based on the view being passed
        }
    
    }
    

    And in your main Activity you could instantiate MyListener and call onClick() and pass your view in it:

    MyListener listener = new MyListener();
    
    Button b = null;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        button = (Button)findViewById(R.id.button);
        listener.onClick(button);
       }
    
    0 讨论(0)
  • 2020-11-27 06:11

    I use button.setOnClickListener(this); where my Activity implements View.OnClickListener, and then get the ID of the Button in a separate method. See below for an example:

    public class MyActivity extends ActionBarActivity implements View.OnClickListener {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.YOUR_LAYOUT);
    
            ...
    
            Button myFirstButton = (Button) findViewById(R.id.YOUR_FIRST_BUTTON);
            myFirstButton.setOnClickListener(this);
    
            Button mySecondButton = (Button) findViewById(R.id.YOUR_SECOND_BUTTON);
            mySecondButton.setOnClickListener(this);
    
            ...
    
        }
    
        ...
    
        @Override
        public void onClick(View v) {
            Button b = (Button) v;
            switch(b.getId()) {
                case R.id.YOUR_FIRST_BUTTON:
                    // Do something
                    break;
                case R.id.YOUR_SECOND_BUTTON:
                    // Do something
                    break;
                ...
            }
        }
    
        ...
    
    }
    
    0 讨论(0)
  • 2020-11-27 06:12

    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 ;)

    0 讨论(0)
  • 2020-11-27 06:13
     public class ProfileDetail extends AppCompatActivity implements View.OnClickListener {
    
              TextView tv_address, tv_plan;
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_profile_detail);
    
    
    
                tv_address = findViewById(R.id.tv_address);
                tv_plan = findViewById(R.id.tv_plan);
    
                tv_address.setOnClickListener(this);
                tv_plan.setOnClickListener(this);
        }
     @Override
        public void onClick(View view) {
                switch (view.getId()) {
                    case R.id.tv_plan:
                        startActivity(new Intent(getApplicationContext(),PlanActivity.class));
                        break;
                    case R.id.tv_address:
                         startActivity(new Intent(getApplicationContext(),AddressActivity.class));
                        break;
                }
            }
    }
    
    0 讨论(0)
  • 2020-11-27 06:19

    It really depends on what you want to achieve. If you have e.g. a complex functionality with threading, dependencies, etc., I personally like to decouple it completely from the Activity into a separate class XyzAction, that does the heavy stuff, knows about certain Invokers and returns them results, if needed. My Invokers are basically objects, that implement OnClick/OnTouch/etc.Listeners and bind themselves to needed actions. E.g. there could be a LoginInvoker implementing OnClickListener for a Button and an ImageView and also a generic ActionListener that gets invoked when a MenuItem is clicked. The Invoker has update methods for showing progress to the user and the result of the bound action. The action posts updates to its Invokers and can be garbage collected, if all of them die, because it has no connection to the UI.

    For less complex actions, I couple them directly to the Android component (i.e. Activity/Feagment/View) and also call them Actions, with the big difference of them implementing the UI callbacks directly.

    In both cases I declare the actions as members, so I can see on a quick glance what specific actions the Android component supports.

    If there's something trivial like "show a Toast if button is pressed", I use anonymous inner classes for the UI callbacks, because you normally don't care that much about them with regards to maintainability.

    0 讨论(0)
提交回复
热议问题