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
Related
I'm just trying to get started with Android development and Kotlin using Jetpack Compose. Note that, I'm a Kotlin novice, so I'm trying to learn along the way. I come from JavaScript/TypeScript background, so I'm trying to learn by thinking in JavaScript terms and implement in Kotlin terms by searching online.
I'm trying to list all installed applications on the device. While the app was working as expected up till now, I needed to add a feature to sort the installed app names. I referred to: https://www.bezkoder.com/kotlin-sort-list-objects/#Create_Class_for_handling_sorting. As soon as I added a custom class to sort the List<ApplicationInfo>, my app stopped building.
I have included my repo here: https://github.com/Hrishikesh-K/TryKotlin
If I comment these lines and this line as well, the app builds fine. With the current setup, I get an error:
Functions which invoke #Composable functions must be marked with the #Composable annotation
which points to line 21, character 18, which is the start of the word compare.
I don't understand why Compose would care about a custom class, it's not a Composable function after all. What am I missing?
In the compare method you are using LocalContext.current
override fun compare(o1 : ApplicationInfo, o2 : ApplicationInfo): Int {
return o1.loadLabel(LocalContext.current.packageManager).toString().compareTo(o2.loadLabel(LocalContext.current.packageManager).toString())
}
You can't use a #Composable functions if the method is not marked with the #Composable.
Use something different like:
data class CompareApplicationNames(val context: Context) : Comparator<ApplicationInfo> {
override fun compare(o1 : ApplicationInfo, o2 : ApplicationInfo): Int {
return o1.loadLabel(context.packageManager).toString().compareTo(o2.loadLabel(context.packageManager).toString())
}
}
Then just use:
Log.d("sorted:", listOfApplications.sortedWith(CompareApplicationNames(LocalContext.current)).toString())
I want to execute a block of code after checking if user is authenticated or not. Something like this:
inline fun <T : Any, R> T?.isUserAuthenticated(callback: (T) -> R) {
FirebaseAuth.getInstance().currentUser?.let {
//Function call
} ?: kotlin.run {
FirebaseAuth.getInstance().signInAnonymously().addOnSuccessListener {
//Function call
}
}
This approach isn't working, but is there any alternative to this?
Inline functions in Kotlin should be used over regular functions when:
You desperately need to allocate memory more efficiently.
When a function accepts another function or lambda as an argument.
You need to prevent object creation and have better control flow.
Otherwise, inlining may cause the generated code to grow. Most likely there are also other situations when it is worth using inline functions but I only added a few (important) of them.
When it comes to checking if a user is authenticated or not, I would rather create a regular function that looks like this:
fun getAuthState() = auth.currentUser != null
And use it:
val isAuthenticated = getAuthState()
if(!isAuthenticated) {
auth.signInAnonymously().addOnCompleteListener(/*...*/)
}
Or if using Kotlin Coroutine:
if(!isAuthenticated) {
auth.signInAnonymously().await()
}
So it's one approach or the other.
I would add this function in a repository class so it can be used all across the entire project.
If you're interested in seeing some code, I recommend you check the following resource:
How to handle Firebase Authentication in clean architecture using Jetpack Compose?
And here is the corresponding repo.
In my Kotlin Multiplatform project, I'm trying to access Kotlin types defined in kotlin-stdlib from Swift.
TL;DR: StdLib types/methods seem not to result in header definitions, I'd like a solution that doesn't involve writing lots of boilerplate code
My scenario
I have an interface defined in Kotlin ...
interface MyKotlinInterface {
fun run() : Sequence<String>
}
... and implemented this interface in Swift ...
class MySwiftClass : MyKotlinInterface {
func run() -> KotlinSequence {
// return sequenceOf("foo")
}
}
... there I'm trying to create a Sequence but there are no methods from the kotlin.sequences package available (e.g. generateSequence).
Is it actually possible to access Kotlin framework types or methods beyond what I define in my code -- if yes, how? Furthermore, how can this be achieved without writing boilerplate code?
Further details
Having a look into the generated Objective-C header file, I see definitions for my class (obviously) and basic Kotlin types. What's missing is basically everything from the standard library functionality (I care for everything Sequence-related).
My build.gradle.kts looks like:
plugins {
kotlin("multiplatform") version "1.3.0"
}
kotlin {
targets { /* ... */ }
sourceSets {
getByName("commonMain") {
dependencies {
api("org.jetbrains.kotlin:kotlin-stdlib-common")
}
}
// ...
getByName("iosMain") {
dependencies {
api("org.jetbrains.kotlin:kotlin-stdlib")
}
}
}
}
Having the kotlin-stdlib defined as a dependency for the iOS target, I would expect those to become actually available from Swift.
Minimal working example
https://github.com/panzerfahrer/so-mwe-kotlin-mpp-swift
Current solution approach
The only solution I came up with, is writing the desired function for the iOS target:
fun <T : kotlin.Any> generateSequence(nextFunction: () -> T?): kotlin.sequences.Sequence<T> = kotlin.sequences.generateSequence(nextFunction)
This works ok-ish but is highly unsatisfying as it requires lots of boilerplate code. Additionally, extension functions cannot be made available this way and would require more boilerplate code or even rewriting parts of the standard library.
Desired solution
I like to avoid writing boilerplate code as much as possible. What I actually only care about, is to have (in my case) Sequence fully accessible from Swift. My feeling is, it would be sufficient to make the compiler generate selected or all header definitions for the standard library functionality.
Do you really need lazy computation (aka Sequence) in your Kotlin code?
If no, I would recommend using List<T> instead (and it maps to Swift directly).
For Sequence implementation, a workaround could be to export a factory function from your Kotlin library, e.g. you may declare a function like
fun <T : kotlin.Any> generateSequence(nextFunction: () -> T?)
= kotlin.sequences.generateSequence(nextFunction)
You may select any other factory function for Sequence, that matches your use-case.
In general, there are too many functions in the Kotlin standard library. Exporting them all to Swift will create too many useless symbols in the binary and increase the compilation time.
Here is a simplified example. This syntax works :
Handler().post({Log.v(TAG, "test")})
However, if I define this function
private fun doWithRunnable(toRun:Runnable) {
// whatever
}
And call it like this
doWithRunnable({Log.v(TAG, "test")})
Then I get the following error:
Required: RunnableFound: () -> Int
Both signatures look quite the same to me... what's the big difference?
In your Java example, you're taking advantage of the Java-interop feature for SAM Conversions. Unfortunately, this does not currently work for Kotlin interfaces, as the designers have deemed it unnecessary (there is some discussion on this see here).
Instead, you'd want to do something like:
fun doWithRunnable(runnable: () -> Any) {
// call it as `runnable()`
}
You could also define a typealias for this if you wanted (which is as close Kotlin comes to SAM syntax):
typealias RunMe = () -> Any
fun doWithRunnable(runnable: RunMe) {
runnable()
}
Note that currently, typealiases have to be declared at the top level, they can't be declared inside a class or method.
Since a while we're working with Kotlin and one of the things we're currently focussing on is using Coroutines to take care of operations we want to run async.
While the example usages are clear and that works, I'm having some issues integrating this in a clean manner within our architecture. When looking at a method's implementation for a domain-focussed class, the idea is that it's easy to read and there is as less "noise" as possible from async functionality. I know I can't have async, without actually using it. So writing something like this is what I'd like:
val data = someService.getData().await()
// work with data
But this is what I'd like to prevent:
launch(UI) {
val data
val job = async(CommonPool) {
data = someService.getData()
}
job.await()
// work with data
}
That, I'd like paired with practical Unit Tests for these domain-focussed classes, but I can't really get that to work. Let's look at an example:
// Some dependency doing heavy work
class ApiClient {
suspend fun doExpensiveOperation(): String {
delay(1000)
return "Expensive Result Set"
}
}
// Presenter Class
class Presenter(private val apiClient: ApiClient,
private val view: TextView) {
private lateinit var data: String
fun start() {
log("Starting Presenter")
runBlocking {
log("Fetching necessary data")
data = apiClient.doExpensiveOperation()
log("Received necessary data")
}
workWithData()
log("Started Presenter")
}
fun workWithData() {
log(data)
}
private fun log(text: String) {
view.append(text+"\n")
}
}
// In an Activity
val presenter = Presenter(ApiClient(), someTextView)
presenter.start()
That works (screenshot: https://imgur.com/a/xG9Xw). Now lets look at the test.
class PresenterTest {
// ... Declared fields
#Before
fun setUp() {
// Init mocks (apiClient, textView)
MockitoAnnotations.initMocks(this)
// Set mock responses
runBlocking {
given(apiClient.doExpensiveOperation()).willReturn("Some Value")
}
presenter = Presenter(apiClient, textView)
}
#Test
#Throws(Exception::class)
fun testThat_whenPresenterStarts_expectedResultShows() {
// When
presenter.start()
// Then
Mockito.verify(textView).text = "Some Value\n"
}
}
Now this test is less than ideal, but regardless, it never even gets to the point where it can verify things work as intended, because lateinit var data wasn't initialized. Now ultimately the aesthetics and readability of our domain classes is simply how far I want to go, which I have some practical working examples for that I'm happy with. But making my tests work seems to be challenging.
Now there's some different write-ups online about this kind of stuff, but nothing has really worked out for me. This (https://medium.com/#tonyowen/android-kotlin-coroutines-unit-test-16e984ba35b4) seems interesting, but I don't like the idea of a calling class launching a context for a presenter, because that in turn has a dependency that does some async work. Although as an abstract thought I like the idea of "Hey presenter, whatever you do, report back to me on a UI context", it rather feels as a fix to make things work, leading to a shared concern for async functionality across different objects.
Anyway, my question:
Moving away from the short examples, does anyone have any pointers on how to integrate coroutines within a bigger architecture, with working unit tests? I'm also very open to arguments that make me alter my way of viewing things, given that's it's convincing on a different level than "If you want things to work, you have to sacrifice.". This question goes beyond just making the example work, as that is just an isolated example, while I'm looking for a real solid integration within a big project.
Looking forward to your input. Thanks in advance.
I'd suggest an approach of having some kind of AsyncRunner interface and have two implementations of this AsyncRunner interface. One would be implementation for Android, using launch(UI), and the other would be some blocking implementation, using runBlocking.
Passing the right type of AsyncRunner into code run within app and code run in unit test should be done by dependency injection. In your code then, you'd not use coroutines directly, instead you'd use injected AsyncRunner to run asynchronous code.
Example implementations of this AsyncRunner might look like this:
interface AsyncRunner {
fun <T>runAsync(task: () -> T, completion: (T) -> Unit)
}
class AndroidCoroutineAsyncRunner: AsyncRunner {
override fun <T>runAsync(task: () -> T, completion: (T) -> Unit) {
launch(UI) {
completion(async(CommonPool) { task() }.await())
}
}
}
class BlockingCoroutineAsyncRunner: AsyncRunner {
override fun <T>runAsync(task: () -> T, completion: (T) -> Unit) {
runBlocking {
completion(async(CommonPool) { task() }.await())
}
}
}
where the task parameter represents the thread blocking code (for example fetching data from API) and completion parameter will get data from the task and do something with them.
You should abandon coroutines and use RxJava instead. There you will find the kind of conciseness and simplicity you seek. When I ask most developers why they use coroutines, their answer is always the same: "Well, coroutines are the new, new thing, and we should use the latest technology from Google". Except that coroutines are not new. They were first introduced in about 1952 (See "Coroutines" in Wikipedia) as a proposal for doing asynchronous software development. It is pretty clear that the Computer Science community rejected coroutines years ago as not being the best approach for asynchronous programming. Why JetBrains decided to introduce an old, rejected technology into Kotlin is something you will have to ask JetBrains. I have had to deal with coroutines in code that others have written for several years now, and I always find coroutines to be needlessly complex. There is no way that coroutines do anything more than decrease maintainability when maintenance developers have to deal with coroutine spaghetti written by a developer who has long since departed the project.
The next thing I hear from these same developers is that RxJava is old technology and coroutines are new technology. If they had done their research, they would never have made such an outrageously incorrect statement. IMHO, RxJava is the most important new development in asynchronous software development in the entire history of computer science.