ButterKnife in BaseActivity and BaseFragment

在日常的开发中,我们经常会遇到这样的场景,几个比较特定的功能或者重复的代码在Activity/Fragment中,我们一般采取的措施就是抽离出来去做一个基类,然后通过子类继承父类的方式来实现。

对于用过ButterKnife的朋友来说,应该已经体会到BF的便捷性和优点。所以理所当然,我们需要把BF放到BaseClass中,节省书写重复代码。

但正如这个issue中JakeWharton说的那样:

Gotcha. Butter Knife is not magical and is actually a very boring, stupid, and predicable library. If you call Butter Knife before setContentView you'll get 0 views.

当你在setContentView之前调用BF的bind,将会返回0个View。

所以需要在BaseClass中做适当的修改,以避免这个问题的发生。

BaseActivity:
@Override
public void setContentView(@LayoutRes int layoutResID) {
    super.setContentView(layoutResID);//基类中复写setContentView方法
    mUnbinder = ButterKnife.bind(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    mUnbinder.unbind();
}

Acvitivty相对来说简单一点,只需要复写setContentView方法,在填充了Layout后,进行BF的绑定即可。

接下来我们看看Fragment的

BaseFragment:
public abstract class BaseFragment extends Fragment {
    private View mRootView;
    private Unbinder mUnbinder;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mRootView = inflater.inflate(getLayout(), container, false);
        mUnbinder = ButterKnife.bind(this, mRootView);

        onSetupView(mRootView);
        return mRootView;
    }

    public View getRootView() {
        return mRootView;
    }

    protected abstract void onSetupView(View rootView);

    protected abstract int getLayout();

    @Override
    public void onDestroy() {
        super.onDestroy();
        mUnbinder.unbind();
    }
}

Fragment由于需要通过inflater填充容器,在填充完毕后还需要进行初始化工作,所以通过两个抽象函数,把具体的实现放在子类中,就可以解决这样的需求。

以上。