Reputation: 1739
I am switching the screen using the Navigation Component
.
In the fragment screen of the bottom A
menu, i can add a recyclerview
item dynamically through the button.
If i press the button on this screen, it moves to another fragment where data can be selected.
If i select data on the converted fragment screen, it returns to the previous screen and adds a recycler view item
based on the selected data.
This process is repeated.
However, even if I repeat this process, the item is not dynamically added.
I add items to the List
of LiveData
by using the ViewModel
, but as a result of debugging, the size of the list type
of LiveData
does not increase from only one.
At least as far as I know the data should be persisted because using viewmodel
is not affected by lifecycle
.
But the problem I have is that it seems to be initialized and saved every time because of the screen change.
Why is this?
ViewModel
class WriteRoutineViewModel : ViewModel() {
private var _items: MutableLiveData<ArrayList<RoutineModel>> = MutableLiveData(arrayListOf())
val items: LiveData<ArrayList<RoutineModel>> = _items
fun addRoutine(workout: String) {
val item = RoutineModel(workout, "TEST")
item.setSubItemList(detailItem)
_items.value?.add(item)
_items.value = _items.value
}
}
Fragment
class WriteRoutineFragment : Fragment() {
private var _binding : FragmentWriteRoutineBinding? = null
private val binding get() = _binding!!
private lateinit var adapter : RoutineAdapter
private val args : WriteRoutineFragmentArgs by navArgs()
private val vm : WriteRoutineViewModel by viewModels { WriteRoutineViewModelFactory() }
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
_binding = FragmentWriteRoutineBinding.inflate(inflater, container, false)
adapter = RoutineAdapter(::addDetail, ::deleteDetail)
binding.rv.adapter = this.adapter
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
args.workout?.let { workout ->
vm.addRoutine(workout)
Toast.makeText(context, workout, Toast.LENGTH_SHORT).show()
}
vm.items.observe(viewLifecycleOwner) { updatedItems ->
adapter.setItems(updatedItems)
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
UPDATE nav_graph
<fragment
android:id="@+id/writeRoutine"
android:name="com.example.lightweight.fragment.WriteRoutineFragment"
android:label="fragment_write_routine"
tools:layout="@layout/fragment_write_routine" >
<action
android:id="@+id/action_writeRoutineFragment_to_workoutListTabFragment"
app:destination="@id/workoutListTabFragment" />
<argument
android:name="workout"
app:argType="string"
app:nullable="true"
android:defaultValue="@null"/>
</fragment>
Upvotes: 1
Views: 571
Reputation: 14817
The view model should have an activity scope for the view model to be able to live throughout the activity lifecycle.
The view model must be initialized like this,
private val model: SharedViewModel by activityViewModels()
This exact use-case is explained in detail in the Android Docs
Upvotes: 2