35
31

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AndroidAdvent Calendar 2014

Day 8

RxAndroid でスクリーンセーバー的な機能を作る

Last updated at Posted at 2014-12-08

 例えば◯秒間操作がなかったらパスキーロック画面を表示する、とかそういうの。普通に作るとタイマーを使って面倒な感じになっちゃいますが、RxJavaRxAndroid を使うととても簡単にできます。

RxJava + RxAnroid の場合

 例えば、画面に EditBoxButton があって、「文字列の入力」と「ボタンが押されたか」を監視、◯秒間操作がなかったら××する、という処理をしたい時、RxJava+RxAndroid では以下のように書けます。

MyActivity.java
public class MyActivity extends Activity {
    private static final String TAG = "MyActivity";
    private Subscription _subscription;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        final EditText editName = (EditText)findViewById(R.id.editName);
        final View buttonOk = findViewById(R.id.buttonOk);

        // OnTextChangeEvent や OnClickEvent をただの Void シグナルに変換
        final Func1<Object, Void> signalizer = new Func1<Object, Void>() {
            @Override
            public Void call(Object onClickEvent) {
                return null;
            }
        };

        // 文字入力イベントのストリームと…
        _subscription = ViewObservable.text(editName).map(signalizer)
                // ボタン押されたのストリームを合体
                .mergeWith(ViewObservable.clicks(buttonOk).map(signalizer))
                // 3秒間なんもなかったらエラーにする
                .timeout(3, TimeUnit.SECONDS)
                .subscribe(new Action1<Void>() {
                    @Override
                    public void call(Void dummy) {
                        // 何かアクションがあったらこっち
                        Log.d(TAG, "文字が入力されたか、ボタンが押されたよ");
                    }
                }, new Action1<Throwable>() {
                    @Override
                    public void call(Throwable throwable) {
                        // 3秒間何もなかったらこっち
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MyActivity.this, 
                                    "3秒間何も操作がありませんでした", Toast.LENGTH_SHORT)
                                    .show();
                            }
                        });
                    }
                });
    }

    @Override
    protected void onDestroy() {
        // イベント系は無限ストリームだから開放してやらないとリークするはず
        _subscription.unsubscribe();
        super.onDestroy();
    }
}

 ViewObservable.text(editName) がテキストが入力される度にシグナルを発するストリーム、ViewObservable.clicks(buttonOk)がボタンが押される度にシグナルを発するストリームです。これらを mergeWith で合体させます。

 あとは timeout につなげるだけ。3秒以内にシグナルがあったら onNext→new Action<Void>()のとこ、3秒以上何も操作がなかったらタイムアウトして onError→new Action<Throwable>() のとこに飛びます。あとはご自由に、ここでは Toast を表示してるだけです。

 注意点は、イベントから生成されたストリームは無限、つまり onComplete は来ない。こういう Observable は自力での購読解除(unsubscribe)が必須です。

これを動かすとこんな感じになります

Xamarin.Android + Rx本家の場合

 さて Xamarin です。Xamarin では本家の Reactive Extensions が使用できます。RxAndroid と同じことをやると下のように書けます、スマート。

MainActivity.cs
[Activity(Label = "RxJavaSample", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        // Set our view from the "main" layout resource
        SetContentView(Resource.Layout.Main);

        var editName = FindViewById<EditText>(Resource.Id.editName);
        var buttonOk = FindViewById<Button>(Resource.Id.buttonOk);

        Observable.FromEventPattern<TextChangedEventArgs>(editName, "TextChanged").Select(_=>true)
            .Merge(Observable.FromEventPattern(buttonOk, "Click").Select(_=>true))
            .Timeout(TimeSpan.FromSeconds(3))
            .Subscribe(_ => {} , 
            e => RunOnUiThread(() => Toast.MakeText(this, 
                "3秒間何も操作がありませんでした", ToastLength.Short).Show()));
    }
}

まとめ

 Reactive Extensions を使うと、UIイベントをストリームに変換でき、合成・加工・フィルタなどして様々な応用ができます。しかしこれは Rx のパワーのまだ半分。もう半分は、WebAPI とか DB とか、Model 由来のレスポンスもストリーム化できること。どちらも Observable にしたら、あとはそれをつなぐだけでアプリ完成!
 さあみんなで Rx にロックインされましょう!

35
31
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
31

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?