Прокрутка к вершине определенного вида вызывает NPE во Fragment? - PullRequest
0 голосов
/ 02 ноября 2019

У меня есть активность и фрагмент. У меня есть две кнопки в действии, и по нажатию обеих кнопок я загружаю один и тот же фрагмент. При втором нажатии кнопки я хочу прокрутить до верхней позиции текстового представления, и фрагмент имеет NestedScrollView в качестве родителя.

Я использую интерфейс, чтобы различать, какая кнопка была нажата

interface HomeFragmentListener {
    fun shouldScrollToCampaign(scroll: Boolean)
}

class MainActivity : AppCompatActivity(),... {

private var homeFragmentListener: HomeFragmentListener? = null

    fun setHomeFragmentListener(homeFragmentListener: HomeFragmentListener? ){
       this.homeFragmentListener = homeFragmentListener
    }

}

Вот мой второй код нажатия кнопки

loadFragment(HomeFragment())
homeFragmentListener?.shouldScrollToCampaign(true)

Загрузка фрагмента выглядит следующим образом

private fun loadFragment(fragment: Fragment?) {
        val transaction = supportFragmentManager.beginTransaction()
        fragment?.let { transaction.replace(R.id.fl_activity_main, it) }
        transaction.commit()
    }

Мой фрагмент выглядит следующим образом

class HomeFragment : Fragment(), HomeFragmentListener {

   override fun shouldScrollToCampaign(scroll: Boolean) {
        if (scroll) {
            nestedScrollView {
                nsv_fragment_home.scrollTo(
                    0,
                    textView.top
                )
            }
        }
    }

 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        (activity as MainActivity).setHomeFragmentListener(this)
..}

}

Я также звоню в сетьКод при загрузке фрагмента

Ответы [ 3 ]

0 голосов
/ 09 ноября 2019

Вы можете вызвать метод во фрагменте, если он уже присоединен к действию. Нажав на вторую кнопку в упражнении, попробуйте это:

var homeFragment = supportFragmentManager.findFragmentById(R.id.fl_activity_main) as HomeFragment
homeFragment.scrolToTop()
0 голосов
/ 11 ноября 2019

Во втором коде вашей кнопки при вызове loadFragment(HomeFragment()) ваш предыдущий фрагмент теперь уничтожен. Ссылка на уничтоженный фрагмент все еще сохраняется в homeFragmentListener. Поэтому, когда вы вызываете метод, реализующий интерфейс, textview будет нулевым. Даже если вы замените на правильный экземпляр, есть 100% -ная вероятность того, что он все равно потерпит неудачу, поскольку жизненный цикл не завершился бы при вызове shouldScrollToCampaign

. Есть два способа решить эту проблему:

  1. Переместите свои кнопки, чтобы фрагментировать и перерисовать представления, которые необходимо обновить.
  2. Если это невозможно или требует слишком большого изменения, пропустите переменную через связку при создании экземпляра фрагмента. и вызовите свою функцию прокрутки после загрузки данных.

    class HomeFragment : Fragment() {
        companion object {
            private const val MY_BOOLEAN = "my_boolean"
    
            fun newInstance(aBoolean: Boolean) = HomeFragment().apply {
                arguments = Bundle(1).apply {
                    putBoolean(MY_BOOLEAN, aBoolean)
                }
            }
        }
    }
    

Вот как можно создать экземпляр HomeFragment и в методе onViewCreated проверить, установлено ли значение MY_BOOLEAN в значение true и на основе этого прокрутки для просмотра вы хотитепрокрутки.

0 голосов
/ 05 ноября 2019

Просто удалите метод set для слушателя и инициализируйте слушателя при создании объекта фрагмента и приведите к интерфейсу.

try:

HomeFragment frg = HomeFragment()
homeFragmentListener = frg as HomeFragmentListener 
loadFragment(frg)
homeFragmentListener?.shouldScrollToCampaign(true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...