引入 Butterknife 库导致片段 class 绑定视图时出现运行时异常
Introducing Butterknife library causes runtime exception in fragment class when binding views
我开始重构我的应用程序以使用 Butterknife 库进行视图绑定。在我的 activity class 中,一切都按预期工作,但我无法理解如何在我的静态片段 class 中正确使用 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)
从堆栈跟踪来看,它看起来像那样,因为我现在正在有效地尝试在 onCreateView()
中绑定 m_ID
和 mTitle
而不是 onItemClick()
回调,这就是为什么视图为空。那是对的吗?我还调用了 Butterknife.bind()
两次,一次是在 onCreteView
中调用 mRecyclerView
和 mFabView
,但 Butterknife.bind()
也在回调中被调用。如何在适当的时候绑定 m_ID
和 mTitle
视图/除了 onCreateView
我应该使用什么方法?
您应该 ButterKnife.bind(...)
仅一次,在 onCreateView()
中,就像您所做的那样。
对于回调,您应该将 View
转换为实际的自定义 View
class(这也绑定了它的小部件!),并获得 title
和 id
从那里:
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);
}
}
然后你必须
从 PlaceholderFragment
中删除 TextView
的引用
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());
希望对你有所帮助
我开始重构我的应用程序以使用 Butterknife 库进行视图绑定。在我的 activity class 中,一切都按预期工作,但我无法理解如何在我的静态片段 class 中正确使用 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)
从堆栈跟踪来看,它看起来像那样,因为我现在正在有效地尝试在 onCreateView()
中绑定 m_ID
和 mTitle
而不是 onItemClick()
回调,这就是为什么视图为空。那是对的吗?我还调用了 Butterknife.bind()
两次,一次是在 onCreteView
中调用 mRecyclerView
和 mFabView
,但 Butterknife.bind()
也在回调中被调用。如何在适当的时候绑定 m_ID
和 mTitle
视图/除了 onCreateView
我应该使用什么方法?
您应该 ButterKnife.bind(...)
仅一次,在 onCreateView()
中,就像您所做的那样。
对于回调,您应该将 View
转换为实际的自定义 View
class(这也绑定了它的小部件!),并获得 title
和 id
从那里:
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);
}
}
然后你必须
从
中删除PlaceholderFragment
TextView
的引用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());
希望对你有所帮助