14
13

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.

DialogFragmentのボタンクリックをObservableにしたい(ただしKotlin)

Last updated at Posted at 2015-05-01

(追記)

この記事のコードはダイアログの再生成時に正常に動作しません。
特別な事情がない限り使用しないことをおすすめします。

はじめに

タイトルの通りですが、DialogFragmentで生成したダイアログのボタンクリックをRxAndroid(RxJava)のObservableとして扱いたくていろいろ試した結果のメモ。

Observableにしたいけど…

個人的な好みの問題だとは思いますがDialogFragmentをshowしたタイミングでObservableを返してほしいと思っています。
ただ、DialogFragmentにおいてダイアログ本体の生成はonCreateDialogで行っているためshowのタイミングではダイアログは生成済みです。
このタイミングでダイアログにボタン&クリックのリスナーを追加してもボタン自体が表示されません。
showの実装を見ると、自分自身をFragmentManagerに追加しているだけなので当然といえば当然ですが…

なので、onCreateDialogで生成したダイアログのボタンクリック時の動作をshowするタイミングで置き換えることにしました。

ObservableなDialogFragment(のダイアログ)

DialogFragment側の実装

showの代わりに実行するshowObservableDialogを実装します。
onCreateDialogの時点では、仮の何もしない関数を突っ込んでおいてObservable.createするタイミングでonNext等々を実行する関数に置き換えます。

LoginDialog
public class LoginDialog : DialogFragment() {

    private var mOnPositiveClick = { }
    private var mOnNegativeClick = { }

    fun showObservableDialog(manager: FragmentManager, tag: String?): Observable<Boolean> {
        super.show(manager, tag)
        return Observable.create<Boolean> {
            mOnPositiveClick = {
                it.onNext(true)
                it.onCompleted()
                this.dismiss()
            }
            mOnNegativeClick = {
                it.onCompleted()
                this.dismiss()
            }
        }.subscribeOn(AndroidSchedulers.mainThread())
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog? {
        return AlertDialog.Builder(getActivity())
                .setTitle(R.string.login)
                .setMessage(R.string.login_message)
                .setPositiveButton(R.string.login, { dialog, witch -> mOnPositiveClick() })
                .setNegativeButton(R.string.cancel, { dialog, witch -> mOnNegativeClick() })
                .create()
    }
}

呼び出し側の実装

今回はこのダイアログが起点になるので、最初にshowObservableDialogしてログインボタンが押されたら続く処理を実行します。
ここではWebViewでOAuth認証してユーザ情報を取得しています。

AuthActivity
LoginDialog().showObservableDialog(getSupportFragmentManager(), null)
                .flatMap { retrieveRequestToken() }
                .flatMap { showLoginWebView(it) }
                .flatMap { retrieveAccessToken(it) }
                .flatMap { getUserInfo(it) }
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe (
                        { success -> this.finish() },
                        { error -> toast("Error!") } )

おわり

面倒なことやってるけど、思ったよりすっきり書けた。
今回の例だとダイアログが起点なのでそこまでの利点は無いけど、処理の途中でダイアログが必要なときは役に立つと思う。

JavaだとInterface使えばやれそう?(試してない)

14
13
1

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
14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?