2014-12-02 7 views
23

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

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? В этом случае я не могу использовать , но я хочу использовать его, потому что он значительно упрощает код.

+0

Разве Guice в значительной степени не делает то же самое лучше, но не испортил ваш код? –

+0

Почему вы думаете, что это испортило код? – Moonlit

+0

@ G_V: Может быть, но Google говорит, что не использовать его. См. Http://stackoverflow.com/questions/24194283/does-avoid-dependency-injection-frameworks-in-the-android-memory-guide-apply-t и http://stackoverflow.com/questions/5067681/guice -performance-на-андроид. –

ответ

44

Прежде всего, 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 звонки.

+1

Благодарим вас за разъяснение. Итак, на ваш взгляд, объявление полей «пакет-частный» или «публичный» не считается плохой практикой? Мне просто интересно, потому что я ВСЕГДА объявил, что мои поля закрыты, и для меня это немного не так. Но в то же время я думаю, что это не имеет большого значения ... правильно? – Moonlit

+8

Я думаю, что пакет-частный достаточно ограничен по объему, что это не имеет большого значения. Если вы не можете доверять другим классам в своем пакете, тогда у вас есть другие проблемы :) Plus package-private также используется для того, чтобы подвергать вещи тестированию классов, поэтому довольно часто это видно. Я бы не стал публичным, но вы все же хотите скрыть эти поля в качестве детали реализации. –

+2

Это делает код, который намного сложнее читать и поддерживать, подвергая вещи, которые нельзя трогать. Вы всегда должны стремиться писать код, который кто-то еще мог бы читать, не тратя часы, чтобы выяснить, что происходит. Это бесполезно для переменных, к которым не следует обращаться за пределами их получателя или сеттера, где у вас есть проверки и другие элементы управления. –