独自リスナーを作成する


Androidにはクリックされた状態を取得するためのonClickListenerなどの便利なリスナーが多くありますが、あるオブジェクトがクリックされた且つ、その他のオブジェクトの状態が変化した場合など、複雑な(あるいはアプリケーション固有の)イベントを取得したい場面がでてきます。

こういった特殊な場合のイベントを通知するために独自のリスナーを作成することができます。

詳細はイカから。

今回はイカの流れでリスナーを作成していきます。

1.EventListenerクラスを継承したInterfaceを作成する(SampleListenerInterface.java)
2.リスナーとしての通知を行うクラスを用意する(SampleNotify.java)
3.リスナーを受け取る(implementsする)処理を実装する(SelfListenerSampleActivity.java)

今回用意したサンプルはボタンをクリックした時にEditTextに文字が入力されていない場合と、入力されている場合のそれぞれの状態を通知するリスナーを実装しています。

イカにサンプルの実行フローを示します。

1.EventListenerクラスを継承したInterfaceを作成する

まずはどんな状態を通知したいかを考え、その状態ごとの通知用メソッドをEventListenerクラスを継承したInterfaceに定義していきます。

今回のサンプルでは、EditTextに文字が入力されていない状態をあらわすnoInputTextメソッドと、EditTextに文字が入力されている状態をあらわすinputTextメソッドを用意しています。

SampleListenerInterface.java

public interface SampleListenerInterface extends EventListener {

    /**
     * 文字が入力されていない状態を通知する
     */
    public void noInputText();


    /**
     * 文字が入力されている状態を通知する
     */
    public void inputText();
}

2.リスナーとしての通知を行うクラスを用意する

リスナーとしての通知を行うクラスを作成します。リスナーはこの通知を行うクラスで、通知用のメソッド(サンプルではnoInputTextメソッドとinputTextメソッド)を呼び出すことで、イベントが発生したことを、リスナーをimplementsしているクラスに通知します。

例えば、onClickListenerでは、Buttonが押下されたタイミングで通知用クラスでonClickメソッドが呼び出されることでonClickListenerをimplementsしたクラスに通知します。

onClickListenerなどのSDKで用意されたリスナーを使う場合には通知用のクラスを意識する必要はありませんが、独自リスナーの場合はこの部分も作成する必要があります。

では実際に1.で作成したリスナーをimplementsしたクラスに通知するためのクラスを作成します。

SampleNotify.java

public class SampleNotify {

    private EditText et = null;
    private SampleListenerInterface listener = null;

    public void SampleNot(EditText et) {
        this.et = et;
    }

    /**
     * EditTextにテキストが入力されているかどうかを判定する
     */
    public void checkText(){
        if(this.listener != null){
            if(this.et.getText().toString().equals("")){
                // テキストが入力されていない場合の通知を行う
                listener.noInputText();
            }else{
                // テキストが入力されている場合の通知を行う
                listener.inputText();
            }
        }
    }

    /**
     * リスナーを追加する
     * @param listener
     */
    public void setListener(SampleListenerInterface listener){
        this.listener = listener;
    }

    /**
     * リスナーを削除する
     */
    public void removeListener(){
        this.listener = null;
    }
}

今回のサンプルではEditTextにテキストが入力されている場合とされていない場合に状態を判定するため、判定対象のEditTextをコンストラクタで取得しています。(6〜8行目)

10〜23行目では、EditTextの入力値を検証し、テキストが入力されている場合とされていない場合のそれぞれの通知を行います。通知先のクラスでこのメソッドを呼び出す事が必要になります。

25〜31行目ではリスナーが実装(implements)されたクラスのインスタンスを取得しています。通知先のクラスでこのメソッドを呼び出す事が必要になります。

33〜38行目ではリスナーが実装(implements)されたクラスのインスタンスを削除しています。リスナーの通知を途中から行いたくない場合に使用します。

3.リスナーを受け取る(implementsする)処理を実装する

最後にリスナーの通知を受け取るクラスを作成します。

public class SelfListenerSampleActivity extends Activity implements OnClickListener, SampleListenerInterface{

    private SampleNotify sn = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        EditText et = (EditText) findViewById(R.id.editText1);
        // 通知用クラスのインスタンス化
        sn = new SampleNotify(et);
        // 通知用クラスに通知先のインスタンスを付加
        sn.setListener(this);

        Button btn = (Button) findViewById(R.id.button1);

        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        // 通知用クラスのメソッドを実行
        sn.checkText();
    }

    @Override
    public void noInputText() {
        Toast.makeText(this, "テキスト空です", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void inputText() {
        Toast.makeText(this, "テキスト入力されてます", Toast.LENGTH_SHORT).show();
    }
}

1行目で1.で作成したリスナーを実装(implements)する宣言を行なっています。(今回はonClickListenerも実装しています。)

14行目ではリスナーを実装(implements)されているクラスのインスタンスを、通知用のクラスに渡しています。この処理が欠けると、通知を受け取ることができません。

24行目では通知用クラスの通知メソッドを実行しています。このメソッドを実行することで、通知が行われ、EditTextの中身によって27〜30行目のメソッド、もしくは32〜35行目のメソッドが実行されます。

27〜30行目、32〜35行目は各通知を受け取った場合に実行したい処理を記述します。

One Comment