JakeWharton / u2020

A sample Android app which showcases advanced usage of Dagger among other open source libraries.
https://www.youtube.com/watch?v=0XHx9jtxIxU
Apache License 2.0
5.68k stars 930 forks source link

Open drawer by clicking toolbar navigation icon #126

Closed kboyarshinov closed 9 years ago

kboyarshinov commented 9 years ago

From TrendingView.java:

  toolbarView.setNavigationOnClickListener(new OnClickListener() {
      @Override public void onClick(View v) {
        // TODO bind to drawer with... injection?
      }
    });

How are you guys planning to implement this binding with MainActivity.drawerLayout?

Typically I'm doing this the following way: ActivityConnector binds to Activity livecycle with attach/detach (e.g. called from onStart/onStop), holds reference to some object in Activity. Simply it looks like this:

public class ActivityConnector<T> {
  private WeakReference<T> ref;

  public void attach(T obj) {
    ref = new WeakReference<T>(obj);
  }

  public void detach() {
    ref = null;
  }

  public T get() {
    return ref == null ? null : ref.get();
  }
}

More robust implementation can be found here.

This approach can be used to bind drawerLayout:

public final class MainActivity extends Activity {
  @Inject ActivityConnector<DrawerLayout> drawerConnector;

  @InjectView(R.id.main_drawer_layout) DrawerLayout drawerLayout;

  @Override protected void onStart() {
    super.onStart();
    drawerConnector.attach(drawerLayout);
  }

  @Override protected void onStop() {
    super.onStop();
    drawerConnector.detach();
  }
}

in TrendingView.java:

@Inject ActivityConnector<DrawerLayout> drawerConnector;
@InjectView(R.id.trending_toolbar) Toolbar toolbarView;

@Override protected void onFinishInflate() {
   super.onFinishInflate();
   ButterKnife.inject(this);

   toolbarView.setNavigationIcon(R.drawable.menu_icon);
   toolbarView.setNavigationOnClickListener(new OnClickListener() {
     @Override public void onClick(View v) {
       DrawerLayout drawer = drawerConnector.get();
       if (drawer != null) {
         drawerLayout.openDrawer(Gravity.START);
       }
     }
   });
}

What do you think about that?

JakeWharton commented 9 years ago

To be honest, I wasn't even going to put an abstract behind it. I was just going to inject the DrawerLayer directly.

The ActivityConnector indirection isn't needed here because we are a view and already have a reference to the activity in the form of its Context.

kboyarshinov commented 9 years ago

Thats true. For single activity binding ActivityConnector brings no benefit. It was initially created to bind multiple activities and store the top most or current for user.

What DrawerLayer do you mean? Doing like ((MainActivity) context).getDrawerLayout().openDrawer(Gravity.START) seems very coupled code.

JakeWharton commented 9 years ago

I meant DrawerLayout. We'd add it to an activity-specific object graph so it could simply be @Injected.

kboyarshinov commented 9 years ago

Ahh, ok, I see. I can do that if you don't mind?

JakeWharton commented 9 years ago

Sure. We have a semi-clever way of obtaining the injector that I'd like to introduce. Let me see if I can get it done here quickly.

On Thu, Apr 2, 2015 at 11:52 PM Kirill Boyarshinov notifications@github.com wrote:

Ahh, ok, I see. I can do that if you don't mind?

— Reply to this email directly or view it on GitHub https://github.com/JakeWharton/u2020/issues/126#issuecomment-89151606.

kboyarshinov commented 9 years ago

Ok. I'm interested what this way is. I was playing around several ways of doing this: using custom system service, or even Mortar. In dagger2, however, obtaining specific component is not so obvious, and I'm still looking for more clean way.

JakeWharton commented 9 years ago

Heh, I did the system service. I think it's the best for this situation in terms of complexity vs. desired result: https://github.com/JakeWharton/u2020/pull/128.

kboyarshinov commented 9 years ago

:+1: fair enough

JakeWharton commented 9 years ago

It's merged. Go nuts!

kboyarshinov commented 9 years ago

Done. #131