Как заменить setTargetFragment() теперь, когда он устарел

#android #android-fragments #androidx #android-preferences

#Android #android-фрагменты #androidx #android-настройки

Вопрос:

setTargetFragment() устарел в Java, и я не понимаю правильной замены для него, поскольку документация Android использует его и устарела. Я считаю FragmentManager , что это правильная замена для него. Я использую устаревшую setTargetFragment функцию в настройках настроек для создания нескольких экранов настроек. Для этого я изначально следовал приведенному здесь руководству, которое ошибочно используется setTargetFragment в примере. Ниже приведен мой код:

 build.gradle (Module: app)
...
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.preference:preference:1.1.1'
...
  
 MainActivity.kt

class MainActivity : AppCompatActivity() {
    private lateinit var settingsButton: ImageButton

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        settingsButton = findViewById(R.id.settingsButtonMain)
        settingsButton.setOnClickListener {
            settingsClicked()
        }
        ...
    }

    private fun settingsClicked() {
        val settingsIntent = Intent(this, SettingsActivity::class.java)
        startActivity(settingsIntent)
    }
}
  
 SettingsActivity.kt

class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment(this)).commit()
        supportFragmentManager.addOnBackStackChangedListener {
            if(supportFragmentManager.backStackEntryCount == 0) {
                title = "App Settings"
            }
        }
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        ...
    }

    class SettingsFragment(cont: Context) : PreferenceFragmentCompat() {
        private var context1: Context = cont

        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.root_preferences, rootKey)
        }
    }

    class Screen2PreferencesFragment : PreferenceFragmentCompat() {
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.screen2_preferences, null)
        }
    }

    override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat?, pref: Preference): Boolean {
        val args: Bundle = pref.extras
        val fragment: Fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment)
        fragment.arguments = args
        fragment.setTargetFragment(caller, 0) //TROUBLE AREA. WHAT IS THE CORRECT REPLACEMENT HERE?
        supportFragmentManager.beginTransaction().replace(R.id.settings, fragment).addToBackStack(null).commit()
        return true
    }

    override fun onSupportNavigateUp(): Boolean {
        if(supportFragmentManager.popBackStackImmediate()) {
            return true
        }
        return super.onSupportNavigateUp()
    }
}
  

Комментарии:

1. Смотрите: Передача результатов между фрагментами

Ответ №1:

Включите эту зависимость:

 implementation 'androidx.fragment:fragment-ktx:1.3.0-beta01'
  

Используйте setFragmentResultListener вместо setTargetFragment() :

 override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat?, pref: Preference): Boolean {
    val args: Bundle = pref.extras
    val fragment: Fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment)
    fragment.arguments = args
    supportFragmentManager.beginTransaction().replace(R.id.settings, fragment).addToBackStack(null).commit()
    
    supportFragmentManager.setFragmentResultListener("requestKey") { key, bundle ->
        if (key == "requestKey") {
            // Get result from bundle
        }
    }
    
    return true
}
  

И в вашем фрагменте, который возвращает результат:

 // Insert result in a bundle
setFragmentResult("requestKey", bundle)
  

Комментарии:

1. setFragmentResultListener неразрешен. Я полагаю, мне нужно реализовать интерфейс?

2. Я думаю, я понял это. Поправьте меня, если я ошибаюсь. setFragmentResultListener на самом деле должно выглядеть так val result = "result" n setFragmentResult("requestKey", bundleOf("bundleKey" to result)) : n FragmentResultOwner необходимо реализовать и переопределить классы здесь (новая строка не отображается в комментарии, поэтому я добавил n там, где она должна быть)

3. Если он не решен, добавьте import androidx.fragment.app.setFragmentResultListener . Создайте пакет, используя bundleOf("bundleKey" to result) и добавьте его в качестве параметра setFragmentResult() , как показано в ответе.

4. Из моего тестирования это определенно требует реализации FragmentResultOwner. Он не работает без или только с предлагаемым импортом (который кажется недействительным). Я ценю помощь.

Ответ №2:

Для нерешенной проблемы при попытке использовать setFragmentResult, ссылающейся на приведенный выше ответ, вы можете попробовать использовать FragmentManager следующим образом.

Это для Xamarin:

 ParentFragmentManager.SetFragmentResult("requestKey", bundle);