Skip to content
This repository has been archived by the owner on Apr 20, 2021. It is now read-only.

Ordering of plugins and the result on the call order

Pascal Welsch edited this page May 8, 2016 · 5 revisions

When adding Plugins to an composition object of CompositeAndroid it works the same as adding one layer of inheritance. When adding two Plugins, two layers of inheritance get created.

Normal Example with calling super

Here are two plugins added.

public class MainActivity extends CompositeActivity {

    public MainActivity() {
        addPlugin(new ViewTrackingPlugin("Main"));
        addPlugin(new DevOptionsPlugin());
    }
}

Spoken in inheritance this means:

class ViewTrackingMainActivity extends MainActivity { ... }

class DevOptionsViewTrackingMainActivity extends ViewTrackingMainActivity { ... }

And this is how the plugins get called. For every method call, the Delegate calls from the more specialized implementation to the more generic. When the Activity calls onResume() the following happens:

AppCompatActivity#onResume()
// calls the corresponding delegate to handle the call

ActivityDelegate#onResume()
// gets the latest added plugin (`DevOptionsPlugin`)
// sets a listener to the DevOptionsPlugin to listen for the super call
// calls DevOptionsPlugin#onResume()

DevOptionsPlugin#onResume()
// runs the code inside DevOptionsPlugin#onResume() until super.onResume() gets called
// the default implementation of every method is simply calling super.onResume()

ActivityDelegate#onResume() (inside DevOptionsPlugin super callback)
// got callback from DevOptionsPlugin#onResume() that super got called
// get next plugin (`ViewTrackingPlugin`)
// sets a listener to the DevOptionsPlugin to listen for the super call
// calls ViewTrackingPlugin#onResume()

ViewTrackingPlugin#onResume()
// runs the code inside ViewTrackingPlugin#onResume() until super.onResume() gets called
// super.onResume() is the first line in the method

ActivityDelegate#onResume() (inside ViewTrackingPlugin super callback)
// got callback from ViewTrackingPlugin#onResume() that super got called
// iterated through all plugins.
// Now call AppCompatActivity super#onResume()
// CompositeAndroid generated a method for it called CompostiteActivity#onResume__super()

CompostiteActivity#onResume__super()
// run code of AppCompatActivity super.onResume()
// method finished go back to caller

ActivityDelegate#onResume() (inside ViewTrackingPlugin super callback)
// Method inside of the ViewTrackingPlugin#onResume super listener callback of finished
// go back to caller

ViewTrackingPlugin#onResume()
// super was called
// run code after super call (which is the view tracking)
// method finished go back to caller

ActivityDelegate#onResume() (inside DevOptionsPlugin super callback)
// Method inside of the ViewTrackingPlugin#onResume finished
// go back to caller

DevOptionsPlugin#onResume()
// super was called
// run code after super call (no code because it's the default implementation)
// go back to caller

ActivityDelegate#onResume()
// called all plugins
// go back to caller

AppCompatActivity#onResume()
// runs code after calling the delegate (no code)
// go back to caller which called Activity#onResume() somewhere inside the Android Framework

Advanced Example with return and not calling super

It's also possible not to call super. This is important for functions like onOptionsItemSelected. In this Example we add a options item and listen for clicks. When the Developer options item got clicked the method returns true because the event is handled by starting an activity. In this case super gets not called.

public class DevOptionsPlugin extends ActivityPlugin {

    public static final String DEVELOPER_OPTIONS_TEXT = "Developer options";

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(DEVELOPER_OPTIONS_TEXT);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        if (DEVELOPER_OPTIONS_TEXT.equals(item.getTitle())) {
            Intent intent = new Intent(Intent.ACTION_VIEW,
                    Uri.parse("mycompany://appname/devoptions"));
            try {
                // note: simply calling startActivity(intent); is not allowed because the call order 
                // would be different. The code before super.startActivity in this plugin would be executed 
                // first before a plugin added later and is more specialized.
                getActivity().startActivity(intent);
            } catch (ActivityNotFoundException e) {
                Toast.makeText(getActivity(), "Couldn't open Activity", Toast.LENGTH_SHORT).show();
            }
            // not calling super!!!
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Execution order in detail:

Activity#onOptionsItemSelected(item)
// calls the corresponding delegate to handle the call

ActivityDelegate#onOptionsItemSelected(item)
// gets the latest added plugin (`DevOptionsPlugin`)
// sets a listener to the DevOptionsPlugin to listen for the super call
// calls DevOptionsPlugin#onOptionsItemSelected(item)

DevOptionsPlugin#onOptionsItemSelected(item)
// runs the code inside DevOptionsPlugin#onResume()
// starts an activity and returns true
// not calling super
// method finishes go back to caller

ActivityDelegate#onOptionsItemSelected(item)
// super listener not called. Not calling through the super implementations
// ViewTrackingPlugin#onOptionsItemSelected(item) will *not* be called
// CompositeActivity#onOptionsItemSelected__super(item) will *not* be called
// Activity#onOptionsItemSelected(item) will *not* be called
// go back to caller

Activity#onOptionsItemSelected(item)
// runs code after calling the delegate (no code)
// go back to caller which called Activity#onOptionsItemSelected(item) somewhere inside the Android Framework