SoFunction
Updated on 2025-04-17

Implementation and comparison of three onClicks in Android

The first method: static inner class + pass View parameters

Implement code

Button btn_toMain2 = findViewById(.btn_toMain2);
btn_toMain2.setOnClickListener(new staticMyOnClickListener(tv_hello));

static class staticMyOnClickListener implements {
    private final TextView tv_hello;

    public staticMyOnClickListener(TextView tv_hello) {
        this.tv_hello = tv_hello;
    }

    @Override
    public void onClick(View view) {
        tv_hello.setTextColor(0xFFFF0000);
    }
}

Features and advantages and disadvantages

advantage:

  • Memory security: Use static inner classes and do not implicitly hold references to external activities
  • Clear responsibilities: click logic is encapsulated in independent classes, complying with the principle of single responsibility
  • Reusable: The same ClickListener can be reused in multiple places

shortcoming:

  • A lot of code: you need to define a class separately
  • Parameter passing trouble: If you need to access multiple Activity members, you need to pass them all through the constructor
  • Not flexible enough: modifying TextView requires recreating the instance

Applicable scenarios:

  • Handle relatively independent and simple click logic
  • The situation where click logic needs to be reused
  • Scenarios with high memory security requirements

The second method: non-static inner class (the sample code is incorrect, it should be non-static)

The corrected implementation code

Button btn_toMain3 = findViewById(.btn_toMain3);
btn_toMain3.setOnClickListener(new MyOnClickListener());

class MyOnClickListener implements {
    @Override
    public void onClick(View view) {
        // You can directly access Activity members        tv_hello.setTextColor(0xFFFF0000);
    }
}

Features and advantages and disadvantages

advantage:

  • Easy access: You can directly access all members of an external activity
  • Concise code: no need to pass parameters
  • Simple implementation: suitable for rapid development

shortcoming:

  • Memory leak risk: Non-static internal classes implicitly hold Activity references, which will cause memory leaks if held by long-lifetime objects.
  • Poor reusability: Strongly coupled with specific activities, difficult to reuse

Applicable scenarios:

  • Simple temporary click processing
  • Determine that the life cycle is short and will not be held externally
  • Scenarios where frequent access to Activity members are required

The third method: Activity implements interface

Implement code

public class MainActivity extends AppCompatActivity implements  {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        (savedInstanceState);
        setContentView(.activity_main);
        
        Button btn_toMain5 = findViewById(.btn_toMain5);
        btn_toMain5.setOnClickListener(this);
    }

​​​​​​​    @Override
    public void onClick(View view) {
        if(() == .btn_toMain5){
            Intent intent = new Intent();
            (this, );
            startActivity(intent);
        }
    }
}

Features and advantages and disadvantages

advantage:

  • Code Settings: All click logic is in one method for easy management
  • Memory security: no memory leak
  • Suitable for multiple controls: suitable for handling click events of multiple controls
  • Concise: no additional class definition is required

shortcoming:

  • Methods are easy to expand: when there are many controls, the onClick method will become huge
  • High coupling degree: strong coupling of click logic and Activity
  • Reduced readability: A large number of if-else or switch-cases reduce readability

Applicable scenarios:

  • Handle click events for a small number of controls
  • Scenarios that need to quickly implement click function
  • A relatively simple application of click logic

Comprehensive comparison table

characteristic Static inner class Non-static internal class Activity implementation interface
Memory security high Low (there is a risk of leakage) high
Code quantity many medium few
Reusability high Low Low
Access Activity members Need explicitly passed Direct access Direct access
Suitable for the number of controls Single/small amount Single/small amount Multiple
Code Organization dispersion dispersion concentrated
Recommended degree ★★★★☆ ★★☆☆☆ ★★★☆☆

Actual development suggestions

1. Priority is given to Lambda expressions (Java 8+):

(v -> {
    // Process click});

Concise and memory-safe, suitable for simple logic

2. Use static inner classes for complex logic:

  • Especially for scenarios that require reuse
  • Or click logic is more complicated and needs to be encapsulated separately

3. Avoid using non-static inner classes:

  • Unless it is ensured that there is no memory leak
  • Or click logic life cycle is exactly the same as Activity

Implementing interfaces are suitable for:

  • Small project or rapid prototyping
  • When click logic is simple and there are not many controls

5. For large projects:

  • Consider using ViewBinding or DataBinding
  • Or use MVVM mode and place the click logic in the ViewModel

Android button click and long press events coexist and status control

1. Implementation method of coexisting and long pressing events and not interfering with each other

Standard implementation method (recommended)

Button myButton = findViewById(.my_button);

// Click event(v -> {
    if (!isLongPress) { // Add flag bit to judge        ("ButtonEvent", "Normal click event triggers");
        // Click event processing logic    }
});

// Long press event(v -> {
    ("ButtonEvent", "Long press event triggers");
    isLongPress = true;
    // Long press event processing logic    
    // Delay reset flag bit    new Handler().postDelayed(() -> isLongPress = false, 300);
    return true; // Must return true to indicate consumption event});

// Class member variableprivate boolean isLongPress = false;

Key points:

  • onLongClickListener must return true, indicating that the event has been consumed, preventing the click event from triggering
  • Use flag bit isLongPress as an additional guarantee
  • Delay reset flags to avoid problems with fast continuous operation

Use time threshold judgment

private long lastEventTime;

((v, event) -> {
    switch (()) {
        case MotionEvent.ACTION_DOWN:
            lastEventTime = ();
            break;
        case MotionEvent.ACTION_UP:
            if (() - lastEventTime < 500) {
                ("ButtonEvent", "Click Event");
            }
            break;
    }
    return false;
});

(v -> {
    ("ButtonEvent", "Long press event");
    return true;
});

Advanced Solution: GestureDetector

class MyGestureListener extends  {
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        ("ButtonEvent", "Click Event");
        return true;
    }

    @Override
    public void onLongPress(MotionEvent e) {
        ("ButtonEvent", "Long press event");
    }
}

// In Activity:GestureDetector gestureDetector = new GestureDetector(this, new MyGestureListener());

((v, event) -> {
    (event);
    return true;
});

2. The button state control method

Basic status settings

// Disable button(false); 

// Enable button(true);

// Check button statusboolean isEnabled = ();

Visual status feedback

<!-- res/drawable/button_state.xml -->
<selector xmlns:andro>
    <item android:state_enabled="false" android:drawable="@drawable/btn_disabled" />
    <item android:state_enabled="true" android:drawable="@drawable/btn_enabled" />
</selector>
// Application status drawable(.button_state);

// Change the text color at the same time(getResources().getColorStateList(.button_text_color));

Use Alpha Transparency to indicate disabled status

(false);
(0.5f); // Translucent effect
(true);
(1.0f); // Restore opaqueness

Comprehensive status management

public class ButtonStateManager {
    public static void disableButton(Button button) {
        (false);
        (0.5f);
        ();
    }
    
    public static void enableButton(Button button) {
        (true);
        (1.0f);
        ();
    }
}

// Use example(myButton);

Using DataBinding (Advanced)

<Button
    android:enabled="@{}"
    android:onClick="@{() -> ()}"
    android:backgroundTint="@{ ? @color/active : @color/inactive}" />

3. Best practice suggestions

1. Event handling selection:

Simple scenario: Use the standard setOnClickListener + setOnLongClickListener combination

Complex gestures: Use GestureDetector

Precise control: Use OnTouchListener to manually handle events

2. Status control suggestions:

Be sure to provide visual feedback when disabling the button

Consider using StateListDrawable to manage different states

All interactive events should be blocked when disabled

3. Performance optimization:

Avoid operating button states in frequently called methods

Consider using a unified tool class for state management of multiple buttons

4. User experience:

It is recommended to keep it between 400-600ms for a long time

You can add Tooltip when disabling the button to explain why

if (!()) {
    ("Please complete the previous operation first");
}

Through the above methods, the perfect coexistence of button clicks and long press events can be achieved, and various states of buttons can be flexibly controlled.

This is the article about the implementation methods and comparisons of three onClicks in Android. For more related content on Android implementation onClick, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!