Подтвердить что ты не робот

Бутерброд Посмотреть инъекции

Я наткнулся на очень интересную библиотеку Injection Dependency под названием ButterKnife. Используя ButterKnife, можно легко вводить представления в действия или фрагменты.

class ExampleActivity extends Activity {
  @InjectView(R.id.title) TextView title;
  @InjectView(R.id.subtitle) TextView subtitle;
  @InjectView(R.id.footer) TextView footer;

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.inject(this);
    // TODO Use "injected" views...
  }
}

Однако, если вы используете Dependency Injection, эти представления должны быть public, чтобы ButterKnife мог его вводить (используя поля private, приводит к исключению fields must not be private or static).

В моем прошлом проекте я всегда делал все поля членов (включая представления) private, поскольку я думал, что это лучшая практика (скрытие информации и т.д.). Теперь мне интересно, есть ли причина, по которой не следует делать все взгляды public? В этом случае я не могу использовать ButterKnife, но я хочу использовать его, потому что он значительно упрощает код.

4b9b3361

Ответ 1

Во-первых, Butter Knife не является библиотекой инъекций зависимостей. Вы можете рассматривать его как библиотеку сокращения шаблонов, поскольку все, что она делает, это замена findViewById и различных вызовов setXxxListener.

Причина, по которой Butter Knife требует, чтобы представления не были частными, это то, что на самом деле генерирует код, который задает поля. Код, который он генерирует, живет в том же пакете, что и ваш класс, поэтому поле должно быть приватным, защищенным или общедоступным. Если поле было приватным, сгенерированный код не смог бы скомпилироваться, поскольку он не может получить доступ к закрытому полю.

Сгенерированный код выглядит примерно так:

public static void inject(ExampleActivity target, ExampleActivity source) {
  target.title = (TextView) source.findViewById(R.id.title);
  target.subtitle = (TextView) source.findViewById(R.id.subtitle);
  target.footer = (TextView) source.findViewById(R.id.footer);
}

Когда вы вызываете ButterKnife.inject(this), он ищет этот сгенерированный класс и вызывает метод inject с вашим экземпляром ExampleActivity в качестве адресата для полей и источника для вызовов findViewById.