Fragment 間の遷移 (5) fragmentを一度だけ生成する

2019年12月16日月曜日

Android Kotlin

t f B! P L

概要

 前回までに、2つのfragmentの間で遷移するところまで作成したが、次の不都合がわかつた。

  • fragmentの実体が想定と異なり、次々と生成されてしまふ
  • 戻るボタンの動作が期待と事なり、第一のfragmentで戻るボタンを押しても、アプリ起動画面に戻らない。
 ここでは、その修正をおこなふ。修正は、以下のやりかたとする。
  • fragmentの実体は、MainFragmentとSecondFragmentとも1つだけ生成する。
  • backStackには、Main→Secondの遷移を1度だけ登録する。

MainFragmentの実体が1回だけ生成するようにする - onCreate() / MainActivity.kt

 ふたつのFragmentにつける名前を決める。

 まず、replace ()の引数に渡す文字列定数を事前に決める。

class MainActivity : AppCompatActivity(), MainFragment.OnButtonClickListener,SecondFragment.OnButtonClickListener2 {

    private val TAGMAIN = "tagMain"
 つぎに、replace( )を実行するときに、引数として上記で設定した Fragment名を渡す。
           supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment.newInstance(),TAGMAIN)
                .commitNow()


 Activityが生成されたときに最初に呼ばれるonCreate( ) の中で実行sれる replace ( )に、第一のfragmentの名前を渡す。 のちほど、第二のフラグメントのボタンでMainFragmentに戻るときに、この名前を鍵にして、MainFragmentの実体が既に存在するか否かを判断するために。

MainFragment への遷移処理 - onButtonClicked2( ) / MainActivity.kt

 第二の fragmentのボタンイベント処理で、つまり、SecondFragmentからMainFragmentに遷移する処理で、以下のやうにして、MainFragmentが既に存在するか否かを判断する。とはいへ、実際には、この処理は冗長で、不要。


override fun onButtonClicked2() {

        var mainFragment = supportFragmentManager.findFragmentByTag(TAGMAIN)
        if (mainFragment == null ) {
            mainFragment = MainFragment()
        }

        supportFragmentManager.beginTransaction().replace(R.id.container, mainFragment, TAGMAIN).commit()
    }

SecondFragment への遷移処理 - onButtonClicked() /MainActivity.kt

 まず、第一のfragmentから、第二の fragmentに、はじめて遷移する場合にのみ、SecondFragmentの実体を生成するやうにする。フラグメントの名前が fragment managerに登録されているか否かで、既に第二のfragmentの実体が生成済か否かを判断してゐる。
 ついで、backStackに既に登録されている 遷移の数を確認する。以下の変数でそれは確認できる。

supportFragmentManager.backStackEntryCount

 この変数の初期値は0。この変数は、addToBackStack( )が呼ばれるたびに+1され、戻るボタンを押して、登録した遷移の逆遷移が行はれたら -1される。
 この変数の値がゼロならば、まだbackStackには遷移が登録されてゐないと判断し、addToBackStack( )を呼ぶことにする。



override fun onButtonClicked() {
 
        var secondFragment = supportFragmentManager.findFragmentByTag(TAGSECOND)
        if (secondFragment == null) {
            secondFragment = SecondFragment()
        }

        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, secondFragment,TAGSECOND)
        if (supportFragmentManager.backStackEntryCount == 0) {
            transaction.addToBackStack(null)
        }
        transaction.commit()
}

  • 3行目:
    • 名前TAGSECONDの fragmentの実体を取得。
  • 4行目:
    • nullならば名前TAGSECONDのfragmentは登録されていない。
  • 5行目:
    • その場合、初めて第二のfragmentへの遷移が発生したとして、SecondFragmentの実体を生成する。
  • 8行目と9行目:
    • 第二の fragmentに遷移する。
  • 10行目:
    • backStackに登録されている遷移の数がゼロならば、Main→Secondへの遷移はまだ登録されてゐないと判断し、
  • 11行目:
    • addToBackStack( )を用ひて遷移を登録する。


MainActivity.ktの全体は次のやうになる。


class MainActivity : AppCompatActivity(), MainFragment.OnButtonClickListener,SecondFragment.OnButtonClickListener2 {

    private val TAGMAIN = "tagMain"
    private val TAGSECOND = "tagSecond"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.container, MainFragment.newInstance(),TAGMAIN)
                .commitNow()
        }
      }

    override fun onButtonClicked() {
        var secondFragment = supportFragmentManager.findFragmentByTag(TAGSECOND)
        if (secondFragment == null) {
            secondFragment = SecondFragment()
        }

        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, secondFragment,TAGSECOND)
        if (supportFragmentManager.backStackEntryCount == 0) {
            transaction.addToBackStack(null)
        }
        transaction.commit()
    }

    override fun onButtonClicked2() {

        var mainFragment = supportFragmentManager.findFragmentByTag(TAGMAIN)
        if (mainFragment == null ) {
            mainFragment = MainFragment()
        }

        supportFragmentManager.beginTransaction().replace(R.id.container, mainFragment, TAGMAIN).commit()
    }
}
(了)


アーカイブ