Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the reverse of using BindView with Butterknife?

Tags:

android

I'm trying to write the below code without using the Butterknife method, mostly for learning purposes. Can anyone help with writing it without it's use please?

I'm guessing it's something along the lines of

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

but it doesn't seem the run the same so I'm guessing I'm missing something

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);
    }
}
like image 626
Mat Avatar asked Dec 22 '25 09:12

Mat


2 Answers

Here is how you can do it when compile SDK version is greater than or equal to 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);
    }
}

For API versions less than 26 you just need to explicit typecast the view returned by findViewById method to the field type.

like image 162
Abdul Wadood Avatar answered Dec 23 '25 23:12

Abdul Wadood


As you probably know, ButterKnife is an annotation processor that takes your code at compile time, evaluates the annotations (eg. @BindView) and generates code to replace them with.

Now in the case of @BindView what the annotation processor actually does is:

  1. find the desired view by its ID

and

  1. cast it to the expected type.

So a functional equivalent of your example would be something like this:

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);
    }
}

You can read more about the underlying processes in this blog post or have a look at some of the ButterKnife source code.

Where you can see that essentially what they do is look for the ID on the source view and try to cast it to the expected type that was read from the annotated field.

Excerpt from 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...
    }
like image 21
Daniel W. Avatar answered Dec 23 '25 22:12

Daniel W.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!