Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Library Modularization via Specialization #172
In an effort to stave off becoming either obsolete or a dumping ground (or both), a few of us have been talking through other channels about how best to approach the future of this library.
Everyone agrees that the current project is a dumping ground of utilities, operators, and helpers that were once useful to one or more people when working with RxJava on Android. These were contributed by a wide variety of people with little thought to what this library's identity would be—they just wanted to share useful code.
Android is an entire platform with vast APIs. Adapting or shimming all of its APIs with RxJava will result in a large, slow moving monolithic library. It would be very hard to dictate policy on naming, reference holding, and behavior across such a large adaptation. And finally, the ways with which developers interact with this large API surface area differs based on use-case, history, and opinion.
It is infeasible to build a single RxAndroid library.
This should come as no surprise as the repo currently doesn't even house a single RxAndroid library. The ill-defined 'framework' module splits functionality in an pre-emptive realization of all the points from above.
I am proposing a from-scratch, modularization of the library into re-usable and composeable modules. A few other notable contributors are in support of this and I'll let them voice their support, suggestions, and/or issues individually.
The APIs in RxAndroid which are fundamental to all RxJava use on the platform deals with threading. Android's hallowed main thread and the related handler-scheduler adapter are fundamental to all RxJava use in a non-trivial capacity. These will be part of the 'core' module.
The newly added plugin hooks are also something foundational with which other modules would leverage functionality. They will also be present in the 'core' module.
Finally, internal static helpers which will be used in all modules (such as the current preconditions/assertions classes) will be in the 'core' to reduce needless duplication.
The second subject on which I want to dedicate a module is binding to and from the UI controls which make up the
The scope of this second module is too large for this issue as there are a lot of considerations to be made around naming, threading, reference keeping, etc. so I will create another issue for that once consensus is reached.
I'll try to preempt answers to some questions below:
This seems drastic. Is this really needed?
It has become very clear to the few of us that have been having conversations that this project is dying. If we do not undertake an effort to make drastic changes such that applications and libraries can confidently depend on it in a way that's useful to everyone then it will simply stagnate into uselessness.
The current offering covers Android APIs randomly, has varying implementations of correctness and efficient, and without a strong idea of an identity no one know what should go in.
Will this be done in an API-compatible way?
No. This will be invasive and destructive. Things will be moving.
What about deprecations?
No. There is no point. We can release
Why from scratch?
This will allow front-loading discussions about naming conventions, implementation patterns, and nuances of things like references. It's much easier to evolve an approach used by all APIs than try to unify 10 different approaches. This does not mean that the existing code will be ignored. It might even be copied verbatim in places, just that it will be all new modules with consistency.
What about activity/fragment lifecycle binding?
That'll potentially be a third module. I personally don't use these so while they are not included in this issue, they will likely be scoped to the same effort.
What about (insert API not mentioned)?
Plan for it to disappear. Copy/paste its implementation into your source tree for continued use after modularization happens. There are plenty of APIs from this library that are used which are useful but have questionable applicability to the masses. If it's specialized enough, consider making a separate library on your personal or corporate GitHub account and depend on one of the modules we will be creating. The point of having small, composeable modules is for a la carte re-use across many libraries.
When will this happen?
If no compelling, well-reasoned, and majorly agreed-upon counter-argument to this approach is to be had we would like to start figuring out the 'core' module in one week. The final current-form release of the library as-is will happen in approximately the same timeline. Once the 'core' module is mostly agreed upon, implementation will start and discussion around the 'ui' module will begin (and will likely be a longer process to flesh out).
How can I help?
Get on board with the effort. Constructive comments, criticisms, and suggestions are welcome. Don't "+1" this issue (we'll see how many read this far). The easiest way to think about this effort is as a new, opinionated, well-designed library driven by a few people who really want it to succeed both in terms of usability to developers but also in being clear in what's appropriate and what's not appropriate for inclusion.
I strongly agree with the separation into modules, as developers can pick themselves which parts to use. The only counter-argument can can think of is that most developers would use most modules anyway, in which case the split might not be as useful, but it wouldn't do much harm (code duplication) either.
I foresee a (4th?) separate module for compat-ui, which contains bindings like the ui module, yet for AppCompat classes. This would actually be another argument FOR the separation of code, as its dependency on appcompat could be restricted to actual users of it. (The same goes perhaps for the Android Design Support Library.)
I have been following the NotRxAndroid project and like the stronger consistency of the API and implementation. For future contributions I would hope to have an even stronger guideline. I have wanted to contribute but as every implementation seems to differ it is hard to fall in line with the correct style. For example, some view bindings allow broadcasting of the initial value and some not. Some allow multiple bindings (via an internal list of listeners) and some not. Would a binding emit the raw events or perhaps the objects that are affected?
+1 all of what Jake said. From my personal standpoint, the project had
I would also vote for not having things like LifeCycleObservable in the
On Tue, Jun 9, 2015 at 10:28 AM, Eric Kok email@example.com wrote:
SoundCloud Ltd. | Rheinsberger Str. 76/77, 10115 Berlin, Germany | +49
Managing Director: Alexander Ljung | Incorporated in England & Wales
Capture and share your music & audio on SoundCloud
Agree with the comments so far. I would propose just releasing and maintaining a core module for now. Maintaining a UI and/or framework module would be cumbersome and as Logan stated I think we can let others create libraries for this and see what shakes out. I unfortunately had to bow out helping refactor the sample app due to all of the framework level contributions. Looking forward to the new direction.
I'm a big fan of this idea. There's no reason to have a single monolithic library when it's easy to add multiple dependencies. The current offerings are a scattershot of ideas with weak cohesion.
By creating a focused core library, we make it easier for others to build on top of RxAndroid. If someone, for example, wants to build an RxAndroidDialog, they could get started with core and build on top of it. This project could move separately from core RxAndroid, so it would have more freedom. In other words, there's no need for non-core functionality to be part of RxAndroid proper.
I think this makes a lot of sense, but I also think that it makes the startup cost of someone new to Rx incorporating the code in their project. Discovering what classes and options becomes harder, especially if you just start out with core and then never find out that their are other modules. I'm not sure the feasibility of this, but I think it would be good to export one combined artifact for people to depend on for debug (if they choose), which would allow for their IDE to index everything all at once. Then, for release they could only compile the modules they needed.
I'm also wary that just simply splitting everything up into modules will really solve the problem at hand. If there was one 'ui' module, that itself would probably become bloated itself since there are so many widgets in the sdk. So one option would be to go module crazy and let people depend on whichever ones they need, but I think this creates a lot of friction for developers to manage. This split does allow people to easily not use any of the ui module and all of core, but I think the same experience could happen in the 'ui' module as is currently happening.
If many worthwhile libraries spin up that all depend on core, but are external to this repo, it may get hard to keep everything in sync, but I think it's probably a problem worth solving. Just wanted to throw it out there.
Seriously though, I approve and applaude the effort, I believe a well though foundation and "extension framework" will not only make everything more stable, but actually faster to move forward.
A list of all associated plugins could still be collected here to make them easily discoverable, maybe through some sort of wizard/configurator; at that point adding a few lines in Gradle won't be a big deal!
It goes without saying, this is the only way to make RxAndroid work.
Happy to follow the lead on this. Just a question about this:
If at all possible, I would prefer to standardize on Google's support annotations instead of Assertions.assertUiThread(). I realize this might not be possible in all cases, but the annotations (e.g., @UiThread) make it faster and easier to do the right thing for most developers. If you don't think this is the appropriate or is too much overhead to include the library, that's fine too!
I'm pretty certain that the static analysis tools are not going to be powerful enough to understand RxJava's scheduler mechanism for moving between threads to accurately prevent people from doing the wrong thing. The use of that helper method is for the thread on which subscription happens, not the thread on which the static factory method is called.
This was referenced
Jun 24, 2015
I like the idea of separating the functionality into modules. If the core module is designed well, someone should be able to create whatever they would like in their own repo as a another module. I'd love to see most of the work on RxAndroid to be done here, but as we have already experienced, everyone has different opinions on how to solve the non-core issues.
As someone else posted above, eventually I'd hope we can sort out what modules are useful/popular, and move them into an RxAndroid organization.
For those of us that would like to participate more closely, what other channels are being used for discussion?