summaryrefslogtreecommitdiff
path: root/java/tests
diff options
context:
space:
mode:
author Joshua Trask <joshtrask@google.com> 2022-12-08 17:50:57 -0500
committer Joshua Trask <joshtrask@google.com> 2022-12-15 17:31:40 +0000
commit3f2db6f582dd9283ad8a582b7ed95c7ce9863399 (patch)
treec1ec570544cbeb020bbc9529bdbf71c08f0ebc56 /java/tests
parent92160d6e9fb1caa1142599ee252f53b796298be5 (diff)
Introduce GenericMultiProfilePagerAdapter
This is an intermediate step in simplifying the full class hierarchy around the MultiProfilePagerAdapters in support of our general interest in clarifying/decoupling the chooser/resolver relationship, and especially in support of our specific goals in being able to build these UIs outside of the chooser/resolver activities (for the embedded sharesheet project). The new class takes over (almost) all of the responsibilities of the two legacy adapter implementations, leaving those components (almost) trivially implemented in terms of this new unified implementation. The remaining responsibilities are extracted to delegate interfaces with corresponding implementations in the legacy components that get injected in the initialization of the new "Generic" base class. (This is just one possible abstraction that I've chosen for now because it trivially preserves the behavior while setting up a structure that's easier to manipulate in our refactoring. In the future, we could consider alternatives -- maybe using simpler "setter" APIs, or adjusting our design to pull these responsibilities out of the adapter altogether.) Following this CL, we should merge this new component up into the base `AbstractMultiProfilePagerAdapter`, then close that API to further extension. We may also remove the use of inheritance as the model for pre-specifying "chooser" vs. "resolver" configurations; we'd only have a single (generic) class, with any behavioral variation configured at initialization time. Notably, the use of generics in the new class replaces a lot of duplication where the chooser implementation just needed to provide overrides to specify the narrower chooser-specific types. I expect that the legacy code has several other places where the chooser-specific version of a class exists largely for these "glue code" responsibilities of switching the entire design over to using the chooser "family" of concrete classes. There's lots of problems with that approach. It's unnecessarily flexible/complex (our application doesn't require runtime polymorphism to select between chooser and resolver implementations); it creates a lot of complex/error-prone situations where the safety of our downcasts relies on our knowledge of how the system is configured at runtime (and our trust in the participating components to honor their [undocumented] contracts); it creates unnecessary coupling and duplication as the configuration has to be pushed through to indirect dependents; and in practice we often have chooser extend resolver instead of pulling up a base class, so the chooser API surfaces grow to accommodate every customization we ever support for the resolver case (often without any particular documentation or contracts for subclass implementors). As in this CL, generics are often the simplest way to preserve the legacy APIs while reducing duplication, and they provide all the flexibility we need since our "app configurations" are static at compile-time. When more runtime flexibility is required, GoF "creational" and "behavioral" patterns specify well-defined alternatives that we should target strictly in our refactorings to prevent the kinds of ad-hoc scope creep that results in our legacy components' current incoherent mix of responsibilities. Test: atest IntentResolverUnitTests Bug: 202167050 Change-Id: I2cde7ee2e0cbed43499bfe457b6b99f239bdfb51
Diffstat (limited to 'java/tests')
0 files changed, 0 insertions, 0 deletions