Implementing Custom Back Navigation in Android - android

I am trying to implement custom back navigation in my fragment based on the documentation here
But when I try to replace the "// Handle the back button event" bit with my back button evet code, my IDE throws up an error saying "Required: OnBackPressedCallback found () -> OnBackPressedCallback"
I am using appcompat:1.0.2. and I have core-ktx:1.0.2'.
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
Here is how I am trying to implement the onBackPressedDispatcher
val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
patientsActivity.moveToLoginScreen(true) // <-- thing I want to happen when the back button is pressed
}
What am I missing here? How do I go about implementing custom back navigation?

The problem with the code is not on the gradle files but on the syntax. The documentation does not provide the proper kotlin code that corresponds to the java code that was given.
Here is the propper way of creating an object of an abstract class - OnBackPressedCallback
val callback = requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
patientsActivity.moveToLoginScreen(true)
}
})
support a change in the documentation here: https://issuetracker.google.com/issues/135469965

OnBackPressedDispatcher is part of the new androidx.activity dependency. The best way to gain access to the new library is to upgrade your version of Fragments:
implementation "androidx.fragment:fragment-ktx:1.1.0-beta01"
By using the fragment-ktx artifact, you also will gain a transitive dependency on activity-ktx, which is what has the Kotlin extension that the documentation uses.

Specifically, you need import androidx.activity.addCallback and in your app build.gradle, implementation "androidx.fragment:fragment-ktx:1.1.0-beta01"

You haven't passed the boolean argument and that is why it doesn't work. The right code is as shown in Jian Astrero's answer. Alternatively, you can use the lambda syntax like this:
val callback = requireActivity().onBackPressedDispatcher.addCallback(this, true) {
patientsActivity.moveToLoginScreen(true)
}
Note that the true passed as second parameter is essential for it to work.

Related

kotlinx.coroutines not found

I'm writing React Native and implemented a custom UI component for Android. One of the props I send to the component is a large array of objects. The deserialization in Android (Kotlin) tooks some time (>200ms) and I'm trying to use async to prevent blocking the UI.
#ReactProp(name = "items")
fun setItems(view: CustomListView, items: ReadableArray) {
async {
val itemsList = deserializItems(items)
view.setItems(itemsList)
}
}
but Android Studio says: Unresolved reference: async
I added these to my app build.gradle:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
and tried to import manually kotlinx.coroutines but Android Studio doesn't find it as well.
How can I get async functionality in Android?
You need a coroutine scope to be able to call async.
I am not familiar with react development, but how i would use it something like this from inside a viewModel.
val asyncFunction = viewModelScope.async {
//do your background work here
}
and then you need to await() it later.
viewModelScope.launch {
asyncFunction.await()
}
For import i have this in the gradle files
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
and these are the imports
import kotlinx.coroutines.*
Also, it might sound silly, but make sure to sync gradle after adding the dependencies.
Or by using the "Sync Now" button displayed on the screen when editing the gradle file.
I solved my problem by adding coroutines dependency.
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4'

How to use kotlin flow flatMap in Android

In my application I want flatMap operators such as flatMapMerge.
But after write codes show me highlight on flatMapMerge and say add one annotation!
I write below codes :
private fun myFunction() {
lifecycleScope.launchWhenCreated {
flowOf("Nerd", "Subby", "Mord")
.flatMapMerge { userInfo(it) }
.collect {
binding.showInfoText.append("$it \n")
}
}
}
Show me below highlight :
When added this annotation : #FlowPreview , then not show this highlight!
But my question is why show this highlight? why I should add this annotation?
What's worked this annotation ?
why show this highlight?
Flow preview has no backward compatibility guarantees, including both binary and source compatibility
why I should add this annotation?
you are accept/agree on the drawback of relying on preview API. In the document they are mentioned , they collecting the feed backs on this.upcoming release they will fix the issue.
refer FlowPreview

*backStack funtions not available in NavController?

Playing with the new fragment navigation, I wanted to dump the current backstack to the log for information purposes to learn how it all works. The problem is, when I obtain the NavController, it doesn't appear to have any of the backstack properties or functions.
Here's a simple example:
class MyFragment: Fragment() {
...
override fun onResume() {
super.onResume()
// Dump the back stack
Log.i("MyFragment", findNavController().currentBackStackEntry?.destination.label)
}
...
In Studio, currentBackStackEntry is not found. It's also true for backStackEntry and previousBackStackEntry (or using the functions explicitly). Of course, when compiling, I get an unresolved reference error.
I'm using:
Android Studio 4.1.1
Kotlin plugin 1.4.10
navigation-fragment-ktx & navigation-ui-ktx 2.3.1
I can use other functions/properties with the NavController, such as obtaining the graph. It's only the *backStack* properties that don't seem to exist.
So, the question is why aren't those properties available, yet documented (they're supposed to be there since navigation-*:2.2.0) and do others see the same issue?

How to get ViewModel in Activity in Android SunFlower Project?

I am studying MVVM of Google Android SunFlower project.
For Fragment, it gets viewmodel like the following
private val plantDetailViewModel: PlantDetailViewModel by viewModels {
InjectorUtils.providePlantDetailViewModelFactory(requireActivity(), args.plantId)
}
I want to try the same method to get viewmodel in Activity. but the requireActivity()show unresolved reference...
And the data binding is not working when I replace it to this.
Does it has other pattern can be use for providePlantDetailViewModelFactory()
Thanks in advance.
You have to add these to your build.gradle
implementation "androidx.core:core-ktx:1.3.1"
implementation "androidx.fragment:fragment-ktx:1.2.5"
Usage in Activity
val usersViewModel: UsersViewModel by viewModels()
Usage in Fragment
// Get a reference to the ViewModel scoped to this Fragment
val viewModel by viewModels<MyViewModel>()
// Get a reference to the ViewModel scoped to its Activity
val viewModel by activityViewModels<MyViewModel>()
You need a gradle dependency on "androidx.activity:activity-ktx:$version".
Then you can import androidx.activity.viewModels in your Activity.
I don't think so that you can do similar for your Activity that's done for Fragment.
Why?
The delegate function viewModels is available from fragment-ktx library (Refer here for reference) as extension for getting ViewModel instance lazily on your value objects using by keyword.
And there's no such thing available for Activities, for an instance.
So, better is to create your own or find some other way like basic lazy{} function from Kotlin standard library and providing logic to it.

How to implement abstract function in Enum constants

What I'm trying to achieve is a simple pattern that I'm using in Java and should be do-able in Kotlin according to the documentation. I just want to declare an enum class with a couple of constant definitions that implement the same abstract functions.
My problem is that I cannot manage to make my code compile. I always get the same error:
modifier abstract not allowed here
Here is the code:
enum class Program {
HOME {
override fun readableName(context: Context): String {
return context.getString(R.string.program_home)
}
},
WEEKEND {
override fun readableName(context: Context): String {
return context.getString(R.string.program_weekend)
}
},
SHOPPING {
override fun readableName(context: Context): String {
return context.getString(R.string.program_shopping)
}
};
abstract fun readableName(context: Context): String
}
I have even tried with the sample code from the documentation and yet even this does not compile.
Could anyone have an idea about this odd issue? Btw I'm currently using Kotlin 1.0.6.
I just tried your code and it's compiled normally with Kotlin plugin 1.0.6-release-Studio2.2-1
Maybe you can just try to update AndroidStudio/Kotlin plugin ?
Alright... so I found out where the issue was and it was not what I expected to be. #Kirill Rakhman was right, there was nothing wrong with the enum code. I had an issue with kapt that was unable for some reason to generate my project annotations. More specifically I was using - what I missed as experimental - the newly available gradle kapt plugin documented here.
I rolled back to the previous kapt settings by replacing
apply plugin: 'kotlin-kapt'
by
kapt {
generateStubs = true
}
And it worked! Not sure why the compilation failed while declaring my enum though.
Thanks a lot for those who took time to look into it and if you have any idea why the experimental kapt plugin was not behaving as expected feel free to comment this answer, I would gladly want to know what happened :)

Categories

Resources