Я создаю приложение Simple Form entry Android, используя компоненты дизайна материалов. В основном работает с нижней навигацией и текстовыми полями. Проблема, с которой я сталкиваюсь, заключается в установке адаптера в раскрывающемся списке textfield . Когда приложение открывается, я получаю надлежащую функциональность, но после поворота адаптер кажется забытым, и единственная опция в выпадающем меню - это текущая выбранная опция перед вращением. Функция setupViews()
в CalculatorFragment
вызывается, но по какой-то причине адаптер настроен неправильно. Представление extIntFront
не доступно нигде в коде, кроме функции setupViews()
, которая вызывается в функции onCreateView
CalculatorFragment
.
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val view = binding.root
setContentView(view)
setupViews()
}
private fun setupViews() = binding.apply {
val navController = findNavController(R.id.nav_host_fragment)
navView.setupWithNavController(findNavController(R.id.nav_host_fragment))
navView.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_item_calculator -> {
if (navController.currentDestination?.id == R.id.navigation_fragment_builder) {
navController.navigate(BuilderFragmentDirections.actionBuilderToCalculator())
}
}
R.id.navigation_item_builder -> {
if (navController.currentDestination?.id == R.id.navigation_fragment_calculator) {
navController.navigate(CalculatorFragmentDirections.actionCalculatorToBuilder())
}
}
}
true
}
}
}
CalculatorFragment.kt (макет, как определено в R.id.navigation_fragment_calculator)
class CalculatorFragment : BaseFragment() {
private val viewModel by viewModels<CalculatorViewModel>()
private val binding: FragmentCalculatorBinding by lazy {
FragmentCalculatorBinding.inflate(layoutInflater)
}
override fun onCreateView (
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
observeEvents()
setupViews()
return binding.root
}
private fun observeEvents() {
viewModel.observeActions {
handleActions(it)
}
viewModel.observeState {
handleState(it)
}
}
...
private fun setupViews() = binding.apply {
...
val items = listOf(getString(R.string.external), getString(R.string.internal))
val adapter = ArrayAdapter(requireContext(), R.layout.list_item, items)
extIntFront.setAdapter(adapter)
extIntFront.setText(getString(R.string.external),false)
...
}
}
Базовый фрагмент.kt
abstract class BaseFragment : Fragment() {
protected val compositeDisposable = CompositeDisposable()
protected inline fun <reified A : Any, reified S : Any> RxViewModel<A, S>.observeActions(
crossinline actionListener: (A) -> Unit = {}
) {
actionsObservable.subscribeBy(onNext = {
actionListener(it)
}, onError = {
Timber.e("Unable to listen for actions: $it")
}).addTo(compositeDisposable)
}
protected inline fun <reified A : Any, reified S : Any> RxViewModel<A, S>.observeState(
crossinline stateListener: (S) -> Unit = {}
) {
stateLiveData.observe(this@BaseFragment, Observer {
stateListener(it)
})
}
override fun onDestroy() {
super.onDestroy()
compositeDisposable.clear()
}
}
RxViewModel.kt
abstract class RxViewModel<A, S> : ViewModel() {
private val _actions = RxEventSender<A>()
val actionsObservable = _actions.observable
protected fun action(action: A) = _actions.send(action)
private val _state = MutableLiveData<S>()
val stateLiveData = _state as LiveData<S>
protected var state: S?
get() = _state.value
set(value) = _state.postValue(value)
}