[JAVA] Practice to use when you want to execute different processing groups serially

Overview

This is a practice when you want to execute different processing groups serially, not limited to Android.

Details

Processing is handled by the concept of Event, and processing is executed through a manager class that executes Events sequentially. Please get the source code from GitHub. https://github.com/ken-maki/k_commons.eventChain

The configuration is as follows.

com.android.k.commons.eventchain ┣lib ┃┣EventChainManager ┃┃ A manager class that executes Events sequentially, a method that interrupts when the processing result of Event fails, and ┃┃ It has a method to execute all Events regardless of the processing result of Event. ┃┣EventChaining ┃┃ Interface for implementing Event. ┣events ┃┣EventFoo ┃┃ Just display the sample event and toast. ┃┣EventBar ┃ ┃ Sample Event, toast display and Event result is returned as false (processing failure). ┃┗EventBaz ┃ Just display the sample event and toast. ┗MainActivity Event Sample Activity to execute.

Source description

Library part

EventChainManager.java


public class EventChainManager {

    List<Pair<EventChaining, Boolean>> mEvents = new ArrayList<Pair<EventChaining, Boolean>>();

    /**
     * add event.
     * <p>
     * added event is serial executed.if event failed, break execute.
     * </p>
     *
     * @param event executable event
     * @return this EventChainManager instance
     */
    public EventChainManager chain(final EventChaining event) {
        mEvents.add(Pair.create(event, false));
        return this;
    }

    /**
     * add event.
     * <p>
     * added event is serial executed.if event failed,  forward next event.
     * </p>
     *
     * @param event executable event
     * @return this EventChainManager instance
     */
    public EventChainManager chainForce(final EventChaining event) {
        mEvents.add(Pair.create(event, true));
        return this;
    }

    /**
     * execute chain events.
     * <p>
     * delete the event after execution
     * </p>
     *
     * @return returns true if it event all succeeds.
     */
    public boolean execute() {
        boolean result = executeAndLeave();
        removeAll();

        return result;
    }

    /**
     * execute chain events.
     * <p>
     * leave the event after execution
     * </p>
     *
     * @return returns true if it event all succeeds.
     */
    public boolean executeAndLeave() {
        for (Pair<EventChaining, Boolean> event : mEvents) {
            EventChaining chainEvent = event.first;
            boolean isForced = event.second;
            if (!chainEvent.action() && !isForced) {
                return false;
            }
        }

        return true;
    }

    /**
     * remove all added Event.
     *
     * @param event event to removed
     */
    public void remove(final EventChaining event) {
        mEvents.remove(event);
    }

    /**
     * remove all added Events.
     */
    public void removeAll() {
        mEvents.clear();
    }
}

A class that executes an Event. There are two methods to add an Event. ・ Chain method If the Event processing result is false (failure), use it when you want to stop the processing there. ・ ChainForce method Used when you want to continue processing regardless of the success or failure of Event processing. After that, start the sequential processing of Events with the execute method. When you want to keep the added Event as it is (when you want to process it again later) after the sequential processing of Events is completed Use the executeAndLeave method.

EventChaining.java


public interface EventChaining {

    /**
     * execute an event.
     *
     * @return returns true if it event succeeds.
     */
    boolean action();
}

A small class, an interface for implementing Events. Write the implementation of Event in the action method. The success or failure of Event processing is returned as boolean.

Individual implementation parts

EventFoo.java


public class EventFoo implements EventChaining {
    Context mContext;

    public EventFoo(final Context context) {
        mContext = context;
    }

    @Override
    public boolean action() {
        Toast.makeText(mContext, "EventFoo executed.", Toast.LENGTH_SHORT).show();
        return true;
    }
}

Implementation of Event. All you have to do is implement Event Chaining and implement the action.

MainActivity.java


public class MainActivity extends AppCompatActivity {

    EventChainManager eventChainManager = new EventChainManager();

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

        final Context context = this;
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                eventChainManager
                        .chain(new EventFoo(context))
                        .chainForce(new EventBar(context))
                        .chain(new EventBaz(context))
                        .execute();
            }
        });


        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                eventChainManager
                        .chain(new EventFoo(context))
                        .chain(new EventBar(context))
                        .chain(new EventBaz(context))
                        .execute();
            }
        });
    }
}

The usage is like this. The points are as follows.

           eventChainManager
                   .chain(new EventFoo(context))
                   .chainForce(new EventBar(context))
                   .chain(new EventBaz(context))
                   .execute();

When using it, if you implement it like this, it will be easy to read that Event is executed serially. In this case, it means that the process is executed up to EventBaz regardless of the process result of the second chained EventBar.

merit

-Improved readability (should) Since you can write events by connecting them using eventChainManager # chain, This series of processes is connected in sequence, and you can express your intention because it is a batch of processes.

Supplement

I thought it was written, but I wonder if it is suitable for cases where complicated processing is executed sequentially.

Source code https://github.com/ken-maki/k_commons.eventChain

Recommended Posts

Practice to use when you want to execute different processing groups serially
When you want to use the method outside
Delegate is convenient to use when you want to reuse parts
When you want to bind InputStream in JDBI3
[Swift] Use nonzeroBitCount when you want popcnt in Swift
What do you use when converting to String?
[Ruby] When you want to replace multiple characters
If you want to use Mockito with Kotlin, use mockito-kotlin
[swift5] How to execute processing when tabBar is tapped
When you want to dynamically replace Annotation in Java8
A memo to check when you try to use Lombok
Code to use when you want to process Json with only standard library in Java
Use JLine when you want to handle keystrokes on the console character by character in Java
When you want to explicitly write OR or AND with ransack
When you want to change the MySQL password of docker-compose
docker-compose.yml when you want to keep mysql running with docker
lombok.config when you want to pass @Qualifier to @RequiredArgsConstructor with lombok
ProxyFactory is convenient when you want to test AOP in Spring!
When you want to ZIP download the image data saved locally
[Docker] Magic command when you want to wipe out none image
When you have introduced devise but want to add more columns
[RSpec] When you want to use the instance variable of the controller in the test [assigns is not recommended]
I want to use FormObject well
[Processing × Java] How to use variables
[Processing × Java] How to use arrays
A memo when you want to clear the time part of the calendar
If you want to use Oracle JDK 11 from September (add Amazon Corretto)
When you want Rails to disable a session for a specific controller only
Summary of means when you want to communicate with HTTP on Android
eclipse I definitely want you to use Transcendental Recommended Shortcut Key (Windows)
[Swift] If you want to use a URL that includes Japanese, use addingPercentEncoding.