Android ViewBinding 替换 findViewById 的神器

ViewBinding中文官网

ViewBinding 的出现就是为了替代 findViewById 的。以前我们写完布局后就要在代码中使用 findViewById 方法找到 xml 文件中对应的 view ,这样耗时费力,还有可能会出错,比如 view 跟 id 不一致等等,奇奇怪怪的问题,毕竟人力和时间有限,这种简单繁杂的工作直接交给 IDE 去做不是更好,它们做的检测工作肯定比人来更精准。

配置

Android Studio 3.6 Canary 11 之后的版本都支持使用ViewBinding这个功能模块了,只需要在 app/build.gradle 文件添加如下代码即可:

	android {
        ...
        viewBinding {
            enabled = true
        }
    }

Android Studio 4.0 后改成了这样:

	android {
        ...
        buildFeatures {
            viewBinding = true
        }
    }

通过上面的配置后,我们工程目录下的 xml 布局文件,就会生成对应的 Binding 类。例如:activity_main.xml 就会生成 ActivityMainBinding 类。这个类就会完成 findViewById 的工作。

当然,如果我们不想我们的 xml 文件生成 Binding 类,我们可以在 xml 布局文件中根 view 写入
tools:viewBindingIgnore="true"

Binding 类生成的路径在build/generated/data_binding_base_class_source_out/debug/out/com/xxx/yyy/databinding/目录下。

我们来看下 ViewBinding 帮我们生成的类的代码结构是怎么样的。

public final class ActivityMainBinding implements ViewBinding {
    @NonNull
    private final ConstraintLayout rootView;
    @NonNull
    public final TextView idText;

    private ActivityMainBinding(@NonNull ConstraintLayout rootView, @NonNull TextView idText) {
        this.rootView = rootView;
        this.idText = idText;
    }

    @NonNull
    public ConstraintLayout getRoot() {
        return this.rootView;
    }

    @NonNull
    public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
        return inflate(inflater, (ViewGroup)null, false);
    }

    @NonNull
    public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, boolean attachToParent) {
        View root = inflater.inflate(2131361820, parent, false);
        if (attachToParent) {
            parent.addView(root);
        }

        return bind(root);
    }

    @NonNull
    public static ActivityMainBinding bind(@NonNull View rootView) {
        int id = 2131165279;
        TextView idText = (TextView)rootView.findViewById(id);
        if (idText == null) {
            String missingId = rootView.getResources().getResourceName(id);
            throw new NullPointerException("Missing required view with ID: ".concat(missingId));
        } else {
            return new ActivityMainBinding((ConstraintLayout)rootView, idText);
        }
    }
}

Android Studio 主要帮我们实现了3个方法,getRoot, inflate, bind 。最重要的就是 bind 方法了。这个方法才是真正实现 findViewById 的地方。

用法

  • Activity 中
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
    setContentView(binding.getRoot());
    binding.idText.setText("ViewBinding");
}
  • Fragment 中

inflate 方法

ActivityMainBinding binding;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    binding = FragmentMainBinding.inflate(inflater, container, false);
    binding.idText.setText("Fragment");
    return binding.getRoot();
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}

或者 bind 方法

FragmentMainBinding binding;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_main, container, false);
}

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    binding = FragmentMainBinding.bind(view);
    binding.idText.setText("Fragment");
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}

同类竞品

  • ButterKnife

通过注解实现 findViewById。

  • Kotlin Android Extensions

通过 Kotlin 语言特性底层实现 findViewById。

  • DataBinding

通过 annotation processor 实现,会影响工程的构建速度。

优点

  • Null 安全

  • 类型安全

总结

ViewBinding 总的来说就是替换 findViewById 的。可以节省我们的开发时间,提高效率。从以前的人工查找绑定,改为 Android Studio 帮助我们查找绑定并生成对应的类。从而帮助开发人员从繁琐的 view 查找绑定中抽身出来,做更有意义的事情。

你可能感兴趣的:(Android,Jetpack)