Butterknife View注射

Moo*_*lit 22 android dependency-injection butterknife

我偶然发现了一个非常有趣的Dependency Injection库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...
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果使用依赖注入这些观点必须publicButterknife能注射它(使用private一个异常场的结果fields must not be private or static).

在我过去的项目中,我总是制作所有成员字段(包括视图),private因为我认为这是最佳实践(信息隐藏等)现在我想知道是否有理由不应该制作所有视图public?在这种情况下,我不能使用,ButterKnife但我想使用它,因为它简化了很多代码.

Jak*_*ton 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);
}
Run Code Online (Sandbox Code Playgroud)

当你调用ButterKnife.inject(this)它时,查找这个生成类并inject使用你的实例调用方法ExampleActivity作为字段的目标和findViewById调用的源.

  • 我认为package-private的范围足够有限,这不是什么大问题.如果您不能信任包中的其他类,那么您还有其他问题:)另外,package-private也用于将事物暴露给测试类,所以看起来很常见.我不会公开,你仍然想隐藏这些字段作为实现细节. (9认同)
  • 好吧,没有getter或setter,注释声明合同.合同如何履行与班级无关.这与普通的`@Inject`注释没有区别,它可以通过反射,代码生成或在测试中手动完成.通过不私有,它也正确地传达了实现字段值的操作不是本地的操作.所以如果有的话,它的语义要比`private`好得多. (3认同)
  • 通过暴露不应该触及的东西,它使代码更难以阅读和维护.您应始终致力于编写其他人无法阅读的代码,而无需花费数小时来弄清楚发生了什么.对于不应在其获取检查和其他控件的getter或setter之外访问的变量,这是无用的. (2认同)