在绑定视图时,引入Butterknife库会导致片段类中的运行时异常

时间:2015-12-29 11:57:41

标签: android android-fragments refactoring butterknife

我开始重构我的应用程序以使用Butterknife库进行视图绑定。在我的活动课中,一切都按预期工作,但我在理解如何在我的静态片段类中正确使用butterknife时遇到了麻烦。我的片段包含一个包含RecyclerView元素列表的CardView适配器。

重构之前

public static class PlaceholderFragment extends Fragment {

        Activity mActivity;
        RecyclerView mRecyclerView;
        TaskAdapter taskAdapter;
        FloatingActionButton mFabView;
        TextView m_ID;
        TextView mTitle;

...

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            mRecyclerView = (RecyclerView) rootView.findViewById(R.id.cardList);
            mFabView = (FloatingActionButton) rootView.findViewById(R.id.normal_plus);

            mFabView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

以及

        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            mRecyclerView.setAdapter(taskAdapter);
            mRecyclerView.setHasFixedSize(true);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            mRecyclerView.setItemAnimator(new DefaultItemAnimator());
            taskAdapter.SetOnItemClickListener(new TaskAdapter.OnItemClickListener() {

                @Override
                public void onItemClick(View v, int position) {
                    m_ID = (TextView) v.findViewById(R.id._task_id);
                    mTitle = (TextView) v.findViewById(R.id.title);
                    Intent detailIntent = new Intent(v.getContext(), DetailActivity.class);
                    detailIntent.putExtra("TASK_ID", m_ID.getText().toString());
                    detailIntent.putExtra("TASK_TITLE", mTitle.getText().toString());

重构后

public static class PlaceholderFragment extends Fragment {

        Activity mActivity;
        TaskAdapter taskAdapter;
        @Bind(R.id.cardList) RecyclerView mRecyclerView;
        @Bind(R.id.normal_plus) FloatingActionButton mFabView;
        @Bind(R.id._task_id) TextView m_ID;
        @Bind(R.id.title) TextView mTitle;

...

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            ButterKnife.bind(this, rootView);

...

        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            mRecyclerView.setAdapter(taskAdapter);
            mRecyclerView.setHasFixedSize(true);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
            mRecyclerView.setItemAnimator(new DefaultItemAnimator());
            taskAdapter.SetOnItemClickListener(new TaskAdapter.OnItemClickListener() {

                @Override
                @OnClick({R.id._task_id, R.id.title})
                public void onItemClick(View v, int position) {
                    ButterKnife.bind(this, v);
                    Intent detailIntent = new Intent(v.getContext(), DetailActivity.class);
                    detailIntent.putExtra("TASK_ID", m_ID.getText().toString());
                    detailIntent.putExtra("TASK_TITLE", mTitle.getText().toString());

我看到的例外是

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.github.idclark.forgetmenot/com.github.idclark.forgetmenot.MainActivity}: java.lang.RuntimeException: Unable to bind views for com.github.idclark.forgetmenot.MainActivity$PlaceholderFragment

...

Caused by: java.lang.RuntimeException: Unable to bind views for com.github.idclark.forgetmenot.MainActivity$PlaceholderFragment
                                                                                    at butterknife.ButterKnife.bind(ButterKnife.java:322)
                                                                                    at butterknife.ButterKnife.bind(ButterKnife.java:279)
                                                                                    at com.github.idclark.forgetmenot.MainActivity$PlaceholderFragment.onCreateView(MainActivity.java:86)
来自堆栈跟踪的

它看起来像是因为我现在有效地尝试绑定m_ID中的mTitleonCreateView()而不是onItemClick()回调,而且&#39} #39;为什么视图为空。那是对的吗?我也Butterknife.bind()两次调用onCreteView mRecyclerViewmFabView,但Butterknife.bind()也会在回调中调用。如何在适当的时间绑定m_IDmTitle视图/我应该使用onCreateView旁边的方法?

1 个答案:

答案 0 :(得分:1)

您应ButterKnife.bind(...) onCreateView() View ,就像您一样。

对于回调,您应该将View投射到实际的自定义title类(这也是绑定它的小部件!),然后获取id和{{1}从那里:

public class MyCustomView extends FrameLayout {

    public @Bind(R.id._task_id) TextView m_ID;
    public @Bind(R.id.title)  TextView mTitle;

    public MyCustomView(Context context) {
        super(context);
        initialize(context);
    }

    public MyCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initialize(context);
    }

    void initialize(Context context) {
        LayoutInflater.from(context).inflate(R.layout.my_custom_view, this);
        ButterKnife.bind(this);
    }
}

然后你必须

  • TextView

    中删除PlaceholderFragment个引用
      TextView m_ID;
      TextView mTitle;
    
  • 修复处理程序:

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mRecyclerView.setAdapter(taskAdapter);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        taskAdapter.SetOnItemClickListener(new TaskAdapter.OnItemClickListener() {
    
            @Override
            @OnClick({R.id._task_id, R.id.title})
            public void onItemClick(View v, int position) {
                MyCustomView myView = (MyCustomView)v;
                Intent detailIntent = new Intent(v.getContext(), DetailActivity.class);
                detailIntent.putExtra("TASK_ID", myView .m_ID.getText().toString());
                detailIntent.putExtra("TASK_TITLE", myView .mTitle.getText().toString());
    

我希望,这有帮助