Log.v(“ThreeTips”, “#10”)

Mert SIMSEK
3 min readDec 26, 2016

--

1- Dagger 2 : Multiple Dependencies, Child Dependencies, explained.

We all have singleton objects in our application lifetime. ApiSource, DataSource, PreferenceHelpers, so on. We declare them as @Singleton in our AppModule.class. We also need to use scopes in our application to control our objects’ scope. If we want one object only in Activity lifetime, we create an @Activity scope and use this in our ActivityComponent as class annotation and ActivityModule as method annotation. Components can share their object with dependent components using dependencies key.

I want to give quick example before dive into dependencies.

Here is the AppComponent.

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
//Dependent components can use this objects

ApiSource apiSource();
Gson gson();
RxBus bus();
}

Here is the component dependent to AppComponent

@Activity
@Component(dependencies = AppComponent.class, modules = MainActivityModule.class)
public interface MainActivityComponent{
void inject(MainActivity activity);

}

It means that we can inject to ApiSource, Gson, RxBus with dependency. It is like inheritance.

Question : What if we want to create two fragment child of that activity and share same object in only Activity lifetime. And we also want to inject ApiSource in child fragments.

Answer : @Subcomponent or dependencies

I will go with dependencies. You can check difference.

In my scenario, I have a ConversationsActivity. And it has 2 fragments. ConversationListFragment and ConversationDetailFragment.

1- ConversationsActivity fetch conversation list over http.

2-Send fetched conversation list to ConversationListFragment

3-Connect sockets in ConversationsActivity to listen new messages.

4-Send socket messages over ReplayBus.

5-ConversationList subscribes to ReplayBus to listen socket messages.

6-ConversationDetail subscribes to ReplayBus to listen socket messages.

A picture is worth a thousand words.

In this dependency architecture, Child fragments can share ReplayBus only in Activity lifetime. Another important point is that If you want to inject object of ancestor (AppComponent) in fragments, you need to declare interface method in dependent module. This is why we declare ApiSource apisource() in ConversationsComponent.

2- Change textStyle using Databinding

If you want to change your textStyle in your xml using databinding library, You need to create binding adapter for it. I thought that textStyle takes an integer as parameter so I could give an integer value using databinding library. But you can not do that. So following is not possible;

public ObservableField<Integer> textStyle;
textStyle = new ObservableField<>(TypeFace.BOLD)

Then call textStyle from xml.

<TextView
android:id="@+id/textViewConversationName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="@{viewModel.textStyle}" />

android:textStyle does not take Integer as param.

So what is the right way to do it? Answer is binding adapter.

public class BindingTextUtils {

@BindingAdapter({"bind:textStyle"})
public static void setTypeface(TextView v, String style) {
switch (style) {
case "bold":
v.setTypeface(null, Typeface.BOLD);
break;
default:
v.setTypeface(null, Typeface.NORMAL);
break;
}
}
}

then change your ObservableField<Integer> to ObservableField<String>.

public ObservableField<String> textStyle;
textStyle = new ObservableField<>("bold")

Then call it from xml.

<TextView
android:id="@+id/textViewConversationName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:textStyle="@{viewModel.textStyle}" />

3- Be careful using animateLayoutChanges

If you have an animation in your View Component like ;

private void animateIt(View viewRoot) {
Animator anim = ...
viewRoot.setVisibility(View.VISIBLE);
anim.setDuration(300);
anim.setInterpolator(new AccelerateInterpolator());
anim.start();
}

And also if you want to animate layout changes in your xml.

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
....</RelativeLayout>

Unfortunately It won’t work. Because you are calling view.setVisibility() before you animate. Relative layout is waiting for this call and apply default animation. So we can say that your animation is overrided by root layout. Solution; remove animateLayoutChanges.

Happy coding.

--

--

Mert SIMSEK
Mert SIMSEK

No responses yet