在不使用Butterknife的监听器中注入视图

时间:2015-05-26 15:14:32

标签: android butterknife

避免"内心的地狱"在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();
    }
}

我的理解在哪里出错?

1 个答案:

答案 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));

        ......

    }

    .....

}