@OnClick array with optional ids (ButterKnife)

victor.alm picture victor.alm · Apr 1, 2015 · Viewed 19.2k times · Source

I have an activity that inflates a view when a web request finished. Some of the widgets of this view have to be attached to one onClick method, so I have:

@OnClick({R.id.bt1, R.id.bt2, R.id.inflated_bt1, R.id.inflated_bt2})
public void onClick(View view) {
    // ...
}

As R.id.inflated_bt1 and R.id.inflated_bt2 don't exist when the app is created, it throws an exception suggesting to set an @Optional annotation.

Required view 'inflated_bt1' with ID XXXXXXXX for method 'onClick' was not found. If this view is optional add '@Optional' annotation.

Is there a way to set some of the views with the @Optional annotation and inject them when the view is inflated? Or, is there another way to do it?

Thank you

Answer

Konrad Krakowiak picture Konrad Krakowiak · Apr 1, 2015

Just add @Optional annotation on the top of your method as is shown in the code below:

@Optional
@OnClick({R.id.bt1, R.id.bt2, R.id.inflated_bt1, R.id.inflated_bt2})
public void onClick(View view) {
    // ...
}

There is a case where you don't have R.id.inflated_bt1 in the layout xml which you use on your Activity. For case like this you have to use @Optional annotation.

When you use only @OnClick annotation in YourClass$$ViewInjector source code looks like below:

view = finder.findRequiredView(source, 2131230789, "method 'onClick'");
view.setOnClickListener(
  new butterknife.internal.DebouncingOnClickListener() {
    @Override public void doClick(
      android.view.View p0
    ) {
      target.onClick();
    }
  });

and the method findRequiredView throws IllegalStateException when view is null.

But when you use additionally @Optional annotation, generated code looks like below

view = finder.findOptionalView(source, 2131230789);
if (view != null) {
  view.setOnClickListener(
    new butterknife.internal.DebouncingOnClickListener() {
      @Override public void doClick(
        android.view.View p0
      ) {
        target.onClick();
      }
    });
}