【问题标题】:What's the reverse of using BindView with Butterknife?将 BindView 与 Butterknife 一起使用的反面是什么?
【发布时间】:2018-04-30 22:05:47
【问题描述】:

我正在尝试在不使用 Butterknife 方法的情况下编写以下代码,主要用于学习目的。有没有人可以帮忙写一下没有用的吗?

我猜是这样的

TextView textName = findViewById(R.id.post_title); 

但它似乎运行不一样所以我猜我错过了一些东西

public class FriendsHolder extends RecyclerView.ViewHolder {
    @BindView(R.id.name)
    TextView textName;
    @BindView(R.id.image)
    CircleImageView imageView;
    @BindView(R.id.title)
    TextView textTitle;
    @BindView(R.id.company)
    TextView textCompany;

    public FriendsHolder(View itemView) {
        super(itemView);
        ButterKnife.bind(this, itemView);
    }
}

【问题讨论】:

    标签: android


    【解决方案1】:

    当编译SDK版本大于等于26时,可以这样做:

    public class FriendsHolder extends RecyclerView.ViewHolder {
        TextView textName;
        CircleImageView imageView;
        TextView textTitle;
        TextView textCompany;
    
        public FriendsHolder(View itemView) {
            super(itemView);
            textName = itemView.findViewById(R.id.name);
            imageView = itemView.findViewById(R.id.image);
            textTitle = itemView.findViewById(R.id.title);
            textCompany = itemView.findViewById(R.id.company);
        }
    }
    

    对于小于 26 的 API 版本,您只需要将 findViewById 方法返回的视图显式类型转换为字段类型。

    【讨论】:

    • 我相信您缺少对字段预期类型的​​显式强制转换。就目前而言,findViewById 只会返回一个 View 对象
    • @DanielW。那是老办法。如果您使用最新的 Android SDK 版本进行编译,则无需显式类型转换。你可以参考stackoverflow.com/questions/44902651/…
    • 太棒了!没有注意到他们改进了这一点。已经使用 Kotlin 这么久了:P ...似乎只有一个小警告。从您链接的答案中:“因此,如果您的 compileSdk 至少为 26,则意味着您可以使用它:)”。也许在你的回答中提到这个限制?以防万一有人绊倒它
    • findViewById() 现在支持泛型:developer.android.com/reference/android/view/…
    • @DanielW。现在我已经添加了。谢谢。
    【解决方案2】:

    您可能知道,ButterKnife 是一个注释处理器,它在编译时获取您的代码,评估注释(例如@BindView)并生成代码以替换它们。

    现在对于@BindView,注解处理器的实际作用是:

    1. 通过 ID 查找所需视图

    1. 将其转换为预期的类型。

    因此,您的示例的功能等价物将是这样的:

    public class FriendsHolder extends RecyclerView.ViewHolder {
    
        private TextView textName;
        private CircleImageView imageView;
        private TextView textTitle;
        private TextView textCompany;
    
        FriendsHolder(View itemView) {
            super(itemView);
            bindViews(itemView);
        }
    
        private void bindViews(View root) {
            textName = (TextView) root.findViewById(R.id.name);
            imageView = (CircleImageView) root.findViewById(R.id.image);
            textTitle = (TextView) root.findViewById(R.id.title);
            textCompany = (TextView) root.findViewById(R.id.company);
        }
    }
    

    您可以阅读更多有关底层进程的信息in this blog post 或查看some of the ButterKnife source code

    您可以看到,他们所做的基本上是在源视图上查找 ID,并尝试将其转换为从注释字段中读取的预期类型。

    摘自butterknife.internal.Utils

    public static <T> T findRequiredViewAsType(View source, @IdRes int id, String who, Class<T> cls) {
        View view = findRequiredView(source, id, who);
        return castView(view, id, who, cls);
    }
    
    public static View findRequiredView(View source, @IdRes int id, String who) {
        View view = source.findViewById(id);
        if (view != null) {
          return view;
        }
        // If view is null throw IllegalStateException
    }
    
    public static <T> T castView(View view, @IdRes int id, String who, Class<T> cls) {
        try {
          return cls.cast(view); // <-- casting 
        } catch (ClassCastException e) {
            throw new IllegalStateException
            // Exception handling...
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 2014-04-15
      • 2017-10-07
      • 2021-02-09
      相关资源
      最近更新 更多