#android #kotlin #android-fragments #android-lifecycle #android-navigation
Вопрос:
Проблема, с которой я столкнулся, кажется довольно странной.
На словах
У меня есть приложение с нижним меню навигации с 3 кнопками, 3 фрагментами для каждой кнопки и одной основной активностью. При переходе к любому из этих фрагментов все работает так, как ожидалось. Проблема возникает, когда я перехожу к другому фрагменту (назовем его фрагментом 4 или fr4) из любого из этих 3 фрагментов. Скажем, я в fr1, у меня есть кнопка, которая переводит меня в fr4. Когда я возвращаюсь к fr1 (либо с помощью кнопки Android назад, либо нажав кнопку нижней панели для fr1), то все, что я делаю в основном действии или любом из 3 фрагментов, повторяется 2 раза. Если я затем снова перейду к fr4, а затем вернусь к fr1, то все повторится 3 раза и так далее.
В приведенном ниже коде fr1-это fragment_home, а fr4-это fragment_profile.
Код
Основная активность.тыс. т
class MainActivity : AppCompatActivity() {
private lateinit var navView: BottomNavigationView
private lateinit var binding: ActivityMainBinding
private val sharedViewModel: SharedViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
navView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_main)
navView.setupWithNavController(navController)
}
override fun onStart() {
super.onStart()
Timber.i("onStart main activity")
}
override fun onStop() {
super.onStop()
Timber.i("onStop main activity")
}
}
framgnet1.kt
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private val sharedViewModel: SharedViewModel by activityViewModels()
private val homeViewModel: HomeViewModel by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
binding.lifecycleOwner = viewLifecycleOwner
binding.sharedViewModel = sharedViewModel
binding.homeViewModel = homeViewModel
binding.historyButton.setOnClickListener{
Timber.i("profile button clicked")
}
binding.profileButton.setOnClickListener { view ->
profileButtonClicked(view)
}
return root
}
fun profileButtonClicked() {
Timber.i("profile button clicked")
val action = HomeFragmentDirections.homeToProfileAction()
NavHostFragment.findNavController(this).navigate(action)
}
}
mobile_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@ id/mobile_navigation"
app:startDestination="@ id/navigation_home">
<fragment
android:id="@ id/navigation_home"
android:name="com.comp.comp.ui.home.HomeFragment"
android:label="@string/title_home"
tools:layout="@layout/fragment_home">
<action
android:id="@ id/home_to_profile_action"
app:destination="@id/fragment_profile"
app:launchSingleTop="true" />
</fragment>
<fragment
android:id="@ id/navigation_dashboard"
android:name="com.comp.comp.ui.dashboard.DashboardFragment"
android:label="@string/title_dashboard"
tools:layout="@layout/fragment_dashboard" >
</fragment>
<fragment
android:id="@ id/navigation_notifications"
android:name="com.comp.comp.ui.notifications.NotificationsFragment"
android:label="@string/title_notifications"
tools:layout="@layout/fragment_notifications" />
<fragment
android:id="@ id/fragment_profile"
android:name="com.comp.comp.fragment_profile"
android:label="fragment_profile"
tools:layout="@layout/fragment_profile" />
</navigation>
Я попытался включить launchSingleTop="true"
навигационное действие, но безрезультатно.
Происходит следующее:
- В домашнем фрагменте, если я нажму кнопку «История», он напечатает «кнопка профиля нажата» один раз
- Если затем я нажму кнопку профиля, приложение перейдет к фрагменту профиля
- Я возвращаюсь к главному фрагменту либо с помощью кнопки «Назад», либо нажатием кнопки «Домой» на нижней панели
- Если я сейчас нажму кнопку «История», «нажата кнопка профиля» будет напечатана дважды.
Если я повторю описанные выше действия, то в следующий раз, когда я нажму кнопку истории, она напечатает «нажата кнопка профиля» 3 раза и так далее.
Я также протестировал переход к другому виду деятельности, onStop()
метод в моей основной деятельности работает в два раза лучше, если я уже был на странице профиля один раз. То же самое, когда я возвращаюсь к основному действию onStart()
, метод выполняется два раза. Все, что я делаю, будет выполняться 2 раза (или более) в зависимости от того, сколько раз я захожу на страницу профиля. Похоже, что он создавал основное действие каждый раз, когда я посещаю страницу профиля, которая одновременно активна. Есть идеи, почему?
Ответ №1:
Я перепробовал все, но безрезультатно. Затем я понял, что при каждом изменении конфигурации он будет сажать новое дерево отладки древесины Джейка Уортона, и он регистрировал все, сколько деревьев было. Надеюсь, это кому-нибудь поможет. Моя ошибка заключалась в том, что строгание древесины было в onCreate основной активности, в то время как оно должно быть в onCreate приложения.