In my activity#1 I create my viewModel like this:
val viewViewModelProvider = ViewModelProviders.of(this)
bluetoothPageViewModel = viewViewModelProvider.get(BluetoothPageViewModel::class.java)
Nice it's work fine.
But I need when forward to another activity (activity#2) to destroy or clear all data in bluetoothPageViewModel.Because when I return (press back button) to activity#1 I need all data in bluetoothPageViewModel to be in init values.
Is it possible.
Related
Suppose I have a notification, that when clicked, launches my app's activity. It's a notification about a message, in a conversation, and so it launches the activity passing the conversationId as an argument. When the activity is launched by that intent from the notification, it should open MessagesScreen, which is a deeply nested screen in the app, passing to it conversationId.
What is the best way to do this in Compose? In the good old Fragments or Activities you just navigated straight to it, but with Compose is a little trickier. The path to the MessagesScreen is as follows:
SplashScreen (checks for authentication) -> HomeScreen (if authenticated) -> ConversationScreen -> MessagesScreen
I can't just navigate straight to MessagesScreen by having the compose's NavController be stored in the Activity, since I need to go through SplashScreen to check for authentication. Also, I don't know the Compose's implication of navigating to a deeply nested component from the Activity's onCreate().
What I currently do is have a field in my global ViewModel called notificationConversationId, that is set on my Activity's onCreate if it was passed by the notification's intent:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val conversationId = intent.getStringExtra("conversation_id") ?: ""
globalViewModel.notificationConversationId = conversationId
// ...
Then, in a LaunchedEffect in my HomeScreen I observe this field, and if it is not empty, I navigate to the MessagesScreen, and set it to an empty string, so the LaunchedEffect is not executed again.
val conversationId = globalViewModel.notificationConversationid
LaunchedEffect(conversationId) {
if (conversationId.isNotEmpty()) {
val path = getMessagespath(conversationId = conversationId)
globalViewModel.notificationConversationId = ""
navController.navigate(path)
}
}
It works, but it is horrendous. Is there a better way to accomplish this in Compose? Thanks in advance.
I'm currently trying to develop a simple app and for my use case is easier to use Composable function for the menu, and then move to an activity for other operations.
Right now I have two classes:
MainActivity: a ComponentActivity that runs some composable functions
NewActivity: an Activity that runs its own class code and has a xml for the design
I successfully managed to move from MainActivity to NewActivity with:
val context = LocalContext.current
val intent = Intent(context, NewActivity::class.java)
startActivity(context, intentntent, null)
Once I reach the NewActivity, I can't however go back to the composable class. In particular, calling back:
val Intent : Intent = Intent(this,MainActivity::class.java)
startActivity(intent)
makes the application stuck.
Is there a way to switch back to the composable class? If not, what alternative do you suggest?
Thanks in advance
Let's say my application has 4 activities (A -> B -> C -> D) when going forward, activity A pass a data value called category to activity B and then activity B pass category and also and data value called level and both used in activity D to get data from firebase realtime database. but when the user goes back to activity C and tries to go again to D data passed from A (category) is now null. so data can't retrieve from firebase. my question is how can I solve this situation.? "I pass data using Intent by putting extras." are there any other ways?
you could use startactivityforresult and set a result intent which includes the data you want to pass back
https://developer.android.com/training/basics/intents/result
You can use a shared ViewModel. Viewmodels are lifecycle-aware components. Data in ViewModels does not disappear when activity changes
Save your data (category,level) in ViewModel like this :
private val _categoryValue =
MutableLiveData<CategoryType>()
val categoryValue:
LiveData<ResponseState<CategoryType> =
_categoryValue
And update your data in activity like this:
vm.categoryValue.value = newCategoryValue
If you are using binding etc. observe and do stuff with your data like this:
vm.deleteFileResponse.observe(this){ category ->
//Do stuff
}
I have a navigation as follows:
FragmentList -> FragmentDetailA -> FragmentDetailB -> FragmentDetailC
I use a viewModel for the detail FragmentDetailViewModel
private val detailViewModel: DetailViewModel by activityViewModels()
But if I go forward, and then back, the above fragmentDetails are changed. How to have a viewmodel assigned to the fragment without changing the others?
Solution:
First of all, change activityViewModels() for viewModels()
Then, the problem was with setFragmentResultListener. It was called before instantiating the new fragment, then the call was made on Fragment A and not on Fragment B. I decided to pass data between destinations with Bundle objects.
Thanks a lot
With this way that you initialized view model, view model depends on the parent activity you must use this way
private val detailViewModel: DetailViewModel by viewModels()
to your view model instance depends on your fragment instance.
It sounds like you want to link the viewmodel to the fragment.
ViewModelProvider(this,viewModelFactory).get(MyViewModel.class)
Long time ago the normal and suggested way on how to communicate between fragments were to create a interface that was extended in Activity. Basically, if I wanted to get data from Fragment B to Fragment C, I had to do Fragment B to MainActivity and then MainActivity to Fragment C. In my view - total mess.
Just started to use LiveData and thought of using it instead of callbacks - for instance:
FragmentInteraction.kt
val onOkayButtonClicked = SingleLiveEvent<Void>()
val onCancelButtonClicked = SingleLiveEvent<Void>()
FragmentA.kt
onOkayButtonClicked.call()
FragmentB.kt
onOkayButtonClicked.observe(viewLifecycleOwner, Observer {
// do whatever u want
})
Does this approach has any down-sides? Is there an easier / more elegant way to approach this?
You could have only one ViewModel(lifecycleOwner = activity), that would have all the liveDataEvents you need for the interactions. You will act on the liveData from the onClick events:
okayButton.setOnClickListener { viewModel.onOkayButtonClicked() }
This LiveData will be observed by the NavigationComponent, or similar you are using for handling fragment transactions, and it will do the transitions for you.
All these transitions I recommend doing them on the Activity level.