0

Android イベント リスナーの場合の「内部クラス地獄」を回避するために、リスナーを別のクラスに移動しました。TextView以下は、日付文字列を保持する のリスナーの 1 つです。それに触れると、 を開き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残りnullNPE. ただし、このコードは、バターナイフを使用しない場合に機能します (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();
    }
}

私の理解はどこが間違っていますか?

4

1 に答える 1

1

バターナイフ インジェクションは、Butterknife.inject()ステートメントがコンストラクターまたは Android ライフサイクル メソッドのいずれかに存在する場合にのみ機能するようです。

したがって、DateViewClickListener呼び出し元のアクティビティを受け入れるようにクラスを変更し、それをバターナイフ インジェクションの「ソース」として次のように使用します。

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

        ......

    }

    .....

}
于 2015-05-27T05:02:20.787 に答える