避免"内心的地狱"在Android事件监听器的情况下,我已将监听器移动到单独的类。以下是TextView
的一个持有日期字符串的侦听器。触摸它后,我打开DatePickerDialog
并将所选日期值设置回TextView
。
我进一步增强了这个监听器,使用Butterknife如下:
public class DateViewClickListener implements View.OnClickListener {
private final DateTime prevDate;
private DateTimeFormatter dateFmt;
public DateViewClickListener(DateTime prevDate, DateTimeFormatter dateFmt) {
this.prevDate = prevDate;
this.dateFmt = dateFmt;
}
@Override
public void onClick(View view) {
new DatePickerDialog(view.getContext(), new DatePickerDialog.OnDateSetListener() {
@InjectView(R.id.date)
TextView dateView;
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
Activity activity = ActivityUtil.getParentActivity(view);
ButterKnife.inject(this, activity.getWindow().getDecorView());
DateTime newDate = prevDate.withDate(year, monthOfYear, dayOfMonth);
dateView.setText(dateFmt.print(newDate));
}
}, prevDate.getYear(), prevDate.getMonthOfYear(), prevDate.getDayOfMonth()).show();
}
}
上述代码中使用的 ActivityUtil.getParentActivity(view)
扫描视图的上下文层次结构并查找其父活动。以下是它的代码:
public class ActivityUtil {
public static Activity getParentActivity(View view) {
Context context = view.getContext();
return scanForActivity(context);
}
private static Activity scanForActivity(Context context) {
if (context == null)
return null;
else if (context instanceof Activity)
return (Activity) context;
else if (context instanceof ContextWrapper)
return scanForActivity(((ContextWrapper) context).getBaseContext());
return null;
}
}
执行此代码时,dateView
仍会null
抛出NPE
。但是,当我不使用Butterknife时,此代码适用于我(在这种情况下DateViewClickListener
类如下)。
public class DateViewClickListener implements View.OnClickListener {
private final DateTime prevDate;
private DateTimeFormatter dateFmt;
public DateViewClickListener(DateTime prevDate, DateTimeFormatter dateFmt) {
this.prevDate = prevDate;
this.dateFmt = dateFmt;
}
@Override
public void onClick(View view) {
new DatePickerDialog(view.getContext(), new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
Activity activity = ActivityUtil.getParentActivity(view);
TextView dateView = (TextView) activity.findViewById(R.id.date);
DateTime newDate = prevDate.withDate(year, monthOfYear, dayOfMonth);
dateView.setText(dateFmt.print(newDate));
}
}, prevDate.getYear(), prevDate.getMonthOfYear(), prevDate.getDayOfMonth()).show();
}
}
我的理解在哪里出错?
答案 0 :(得分:1)
似乎Butterknife注入只有在构造函数或任何Android生命周期方法中存在Butterknife.inject()
语句时才有效。
因此,我修改了DateViewClickListener
类以接受它被调用的活动并将其用作"源"对于Butterknife注射类似于:
public class DateViewClickListener implements View.OnClickListener {
@InjectView(R.id.date)
TextView dateView;
private final DateTime prevDate;
private DateTimeFormatter dateFmt;
public DateViewClickListener(DateTime prevDate, DateTimeFormatter dateFmt, Activity contextActivity) {
Butterknife.inject(this, contextActivity);
this.prevDate = prevDate;
this.dateFmt = dateFmt;
}
.....
}
然后将侦听器实例化为:
public class MainActivity extends ActionBarActivity {
.....
@Override
protected void onCreate(Bundle savedInstanceState) {
......
date.setOnClickListener(new DateViewClickListener(paymentDate, dateFmt, this));
......
}
.....
}