tag:blogger.com,1999:blog-85309064602336707402024-03-08T08:51:27.123-08:00Jelly Beans, SirAndroid related stuffUnknownnoreply@blogger.comBlogger1125tag:blogger.com,1999:blog-8530906460233670740.post-15621241892844614082015-05-06T13:49:00.004-07:002015-05-06T13:49:51.440-07:00Component Dependency vs Submodules in Dagger 2<div>
<span style="font-family: Verdana, sans-serif;"><b>Dagger</b> is a Dependency Injection library created for Java with Android in mind.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">The first its version was by far not the easiest library to catch up. This might relate to the fact it is going well until you do something wrong. What I really like about its <a href="http://google.github.io/dagger/">second release</a> is its clarity. The generated code looks as a human wrote it, it is a pleasure to debug it, not to mention it is up to 13% faster. What's more, when you do something wrong it tells you what's exactly the problem. </span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<div>
<span style="font-family: Verdana, sans-serif;">Android Community is quite loud about it and you can find a lot of really cool materials to familiarize yourself with the library or find comprehensive articles about a migration process, what wasn't really a case with it predecessor. These are just several of what I really enjoyed, I would totally recommend you to go through them:</span><br />
<div>
<ul>
<li><span style="font-family: Verdana, sans-serif;"><a href="http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android/">Tasting Dagger 2 on Android</a> from <a href="http://fernandocejas.com/">Fernando Cejas</a></span></li>
<li><span style="font-family: Verdana, sans-serif;"><a href="http://blog.gouline.net/2015/05/04/dagger-2-even-sharper-less-square/">Dagger 2: Even sharper, less square</a> from Mike Goulin</span></li>
<li><a href="http://siphon9.net/loune/2015/04/dagger-2-0-android-migration-tips/"><span style="font-family: Verdana, sans-serif;">Dagger 2.0 Android migration tips</span></a></li>
</ul>
<div>
<span style="font-family: Verdana, sans-serif;">Despite its clarity, there were some things I stuck with. Most of them are well covered in aforementioned articles but here is also a thing with previously called scoped graphs which exhibit as submodules now. </span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">What was cool about <i>scoped graphs</i> is that you were able to extend an <i>object graph</i> at runtime and not create a bunch of objects unless you really need them. I used to treat scoped graphs per Fragment, but I saw many people deal with their Activities as a standalone unit. That being sad, you could extend the graph with required dependencies (say 'fragment's dependencies' mean '<a href="http://antonioleiva.com/mvp-android/">MVP pattern</a>') for particular Fragment and use the memory somewhat wisely. Surely it is only one of many applications of scoped graphs.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">If you refer to the official documentation there are two ways to achieve the same result: <b>Component Dependency </b>and <b>Subcomponents</b>. Authors are <a href="http://google.github.io/dagger/api/latest/dagger/Component.html">quite clear</a> about the distinction but for me at first it was crystal clear when to use what. </span></div>
</div>
</div>
</div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<h3>
<span style="font-family: Verdana, sans-serif;">Component Dependency</span></h3>
<div>
<span style="font-family: Verdana, sans-serif;">Let's say, you have an <b>ApplicationComponent</b> which holds a <i>Module</i> with all <i>Android </i>related stuff like <i>LocatioService, Resources, LayoutInflater, </i>i.e. everything a <i>Context</i> is needed for<i>. </i></span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">You also may want to have a <b>DataComponent</b> where you manage things for data persistence along with <i>WebService APIs. </i></span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">The only thing you lack in <b>DataComponent </b>is a <i>Context </i>which resides in <b>ApplicationComponent</b>. That's where Component Dependency comes into play. You only need to declare a dependency of a <b>DataComponent </b>on <b>Application component </b>and you have a <i>Context </i>to deal with.</span></div>
<div>
<br /></div>
<div>
<span style="font-family: Verdana, sans-serif;">Here is one important note, you must have a <i>Context</i> explicitly declared in <b>ApplicationComponent </b>because it is the only way you can consume objects from a parent <i>Component. </i>All objects from its <i>Modules </i>aren't available to a child module.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<h3>
<span style="font-family: Verdana, sans-serif;">Subcomponents</span></h3>
<div>
<div>
<span style="font-family: Verdana, sans-serif;">For me, <i>subcomponents</i> are the same <i>scoped graphs. </i>The main difference with <b>Component Dependency</b> is when you hook into <i>parent</i> Component you get an access to <i>all </i>objects from <i>all </i>modules it possesses without an explicit declaration of those dependencies in the parent Component. </span></div>
</div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">Let's assume you have another <i>component </i>solely for your LoginFragment dependencies - <b>LoginComponent</b>. It contains a <i>Presenter</i> where you move all business logic. The <i>Presenter </i>wants to invoke a <i>WebSerivice's </i>method to grab some data from a web service, so it has a dependency on the <i>WebService </i>which we know lives in <b>DataComponent</b>.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">This time you don't need to specify anything in your <b>LoginComponent</b>,<b> </b>but you do in <b>ApplicationComponent</b>. You need to declare the <b>ApplicationComponent </b>could possibly be extended with <b>LoginComponent</b> and you just add something like:</span></div>
<div>
<br />
<pre data-codota-status="done" data-csrftoken="rwp17iov-QV1KuGDpxjhZ3kZAmcm5kcYd8Mc" data-original-code="@Component(/* … */)
interface MyComponent {
/* … */
/* Functionally equivalent to objectGraph.plus(childGraphModule). */
MySubcomponent plus(ChildGraphModule childGraphModule);
}
" data-snippet-id="ext.8e8a53f207b830e40e697daaba0440b9" data-snippet-saved="false" style="color: rgba(0, 0, 0, 0.870588); font-family: Inconsolata, monospace; font-size: 13px; line-height: 20px;"><code class="language-java" data-lang="java" style="font-family: Inconsolata, monospace;"><span class="n">LoginComponent</span> <span class="nf" style="color: #990000; font-weight: bold;">plus</span><span class="o" style="font-weight: bold;">(</span><span class="o">LoginModule module</span><span class="o" style="font-weight: bold;">);</span></code></pre>
<br /></div>
<div>
<span style="font-family: Verdana, sans-serif;">And you need to manually hook into <b>ApplicationComponent</b> to get its object's (<i>all </i>its objects) as something like:</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<pre data-codota-status="done" data-csrftoken="rwp17iov-QV1KuGDpxjhZ3kZAmcm5kcYd8Mc" data-original-code="@Component(/* … */)
interface MyComponent {
/* … */
/* Functionally equivalent to objectGraph.plus(childGraphModule). */
MySubcomponent plus(ChildGraphModule childGraphModule);
}
" data-snippet-id="ext.8e8a53f207b830e40e697daaba0440b9" data-snippet-saved="false" style="color: rgba(0, 0, 0, 0.870588); font-family: Inconsolata, monospace; font-size: 13px; line-height: 20px;">getApplicationComponent().<span style="color: #990000; font-weight: bold;">plus</span>(new LoginModule(this));</pre>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Verdana, sans-serif;">Don't forget to annotate your child module with <b>@Subcomponent</b> instead of <b>@Component</b> if you'd like to treat it as a subcomponent.</span></div>
Unknownnoreply@blogger.com10