Categories
discuss

@composable invocations can only happen from the context of an @composable function

I’m trying to show a toast message when clicking on a toolbar action, but I got this error

@composable invocations can only happen from the context of an @composable function

Code:

@Composable
fun Toolbar() {
    TopAppBar(title = { Text(text = "Jetpack Compose") }, navigationIcon = {
        IconButton(onClick = {}) {
            Icon(Icons.Filled.Menu)
        }
    }, actions = {
        IconButton(onClick = {
            showMessage(message = "test")
        }) {
            Icon(vectorResource(id = R.drawable.ic_baseline_save_24))
        }
    })
}

@Preview
@Composable
fun ToolbarPreview(){
    Toolbar()
}

@Composable
fun showMessage(message:String){
    Toast.makeText(ContextAmbient.current, message, Toast.LENGTH_SHORT).show()
}

Answer

The onClick parameter doesn’t accept a composable function. Remove the @Composable annotation in the showMessage.
Use something like:

@Composable
fun Toolbar() {

    val context = LocalContext.current

    TopAppBar(title = {},
            actions = {
        IconButton(onClick = {
            showMessage(context, message = "test")
        }){}
    })
}

fun showMessage(context: Context, message:String){
    Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
Categories
discuss

LazyColumnFor is not smooth scrolling

So, I have implemented a lazycolumnfor to work with a list of recipe elements, the thing is that it does not smooth scroll, if I just scroll fast it stutters till the last element appears and not smooth scroll.

Is this an error from my side or do I need to add something else?

    data class Recipe(
            @DrawableRes val imageResource: Int,
            val title: String,
            val ingredients: List<String>
    )
    
    val recipeList = listOf(
            Recipe(R.drawable.header,"Cake1", listOf("Cheese","Sugar","water")),
            Recipe(R.drawable.header,"Cake2", listOf("Cheese1","Sugar1","Vanilla")),
            Recipe(R.drawable.header,"Cake3", listOf("Bread","Sugar2","Apple")))
    
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                RecipeList(recipeList = recipeList)
            }
        }
    }
    
    @Composable
    fun RecipeCard(recipe:Recipe){
        val image = imageResource(R.drawable.header)
        Surface(shape = RoundedCornerShape(8.dp),elevation = 8.dp,modifier = Modifier.padding(8.dp)) {
            Column(modifier = Modifier.padding(16.dp)) {
                val imageModifier = Modifier.preferredHeight(150.dp).fillMaxWidth().clip(shape = RoundedCornerShape(8.dp))
                Image(asset = image,modifier = imageModifier,contentScale = ContentScale.Crop)
                Spacer(modifier = Modifier.preferredHeight(16.dp))
                Text(text = recipe.title,style = typography.h6)
                for(ingredient in recipe.ingredients){
                    Text(text = ingredient,style = typography.body2)
                }
            }
        }
    }
    
    @Composable
    fun RecipeList(recipeList:List<Recipe>){
        LazyColumnFor(items = recipeList) { item ->
            RecipeCard(recipe = item)
        }
    }

@Preview
@Composable
fun RecipePreview(){
    RecipeCard(recipeList[0])
}

Answer

Currently (version 1.0.0-alpha02) Jetpack Compose has 2 Composable functions for loading image resources:

  1. imageResource(): this Composable function, load an image resource synchronously.

  2. loadImageResource(): this function loads the image in a background thread, and once the loading finishes, recompose is scheduled and this function will return deferred image resource with LoadedResource or FailedResource

So your lazyColumn is not scrolling smoothly since you are loading images synchronously.

So you should either use loadImageResource() or a library named Accompanist by Chris Banes, which can fetch and display images from external sources, such as network, using the Coil image loading library.

UPDATE:

Using CoilImage :

First, add Accompanist Gradle dependency, then simply use CoilImage composable function:

    CoilImage(data = R.drawable.header) 

Using loadImageResource() :

    val deferredImage = loadImageResource(
        id = R.drawable.header,
    )

    val imageModifier = Modifier.preferredHeight(150.dp).fillMaxWidth()
        .clip(shape = RoundedCornerShape(8.dp))
    deferredImage.resource.resource?.let {
        Image(
            asset = it,
            modifier = imageModifier
        )
    }

Note: I tried both ways in a LazyColumnFor, and although loadImageResource() performed better than imageResource() but still it didn’t scroll smoothly.

So I highly recommend using CoilImage

Note 2: To use Glide or Picasso, check this repository by Vinay Gaba

Categories
discuss

isCoreLibraryDesugaringEnabled not works in gradle kotlin dsl / kts

To enable desugaring in our android-library module we must put this in build.gradle:

android {
  compileOptions {
    coreLibraryDesugaringEnabled true
  }
}

But we have all scripts migrated to gradle kotlin dsl, so the problem occurs in build.gradle.kts in all three ways:

android {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}
configure<BaseExtension> {
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }
}
android {
    if (this is com.android.build.api.dsl.LibraryExtension<*, *, *, *, *, *, *, *, *, *, *>) {
        buildFeatures.viewBinding = true
    }
}

Every time it throws Unresolved reference: isCoreLibraryDesugaringEnabled.

Does anybody have an idea how to fix this?

Answer

When I switch to the newer android plugin version (4.1.0-rc02) it theoretically works. IDE says it’s bad syntax, but it works during compilation.

if (this is com.android.build.api.dsl.LibraryExtension<*, *, *, *, *>) {
    compileOptions.isCoreLibraryDesugaringEnabled = true
}

However, it’s not an ideal solution

—– FINAL SOLUTION —–

Solution is similar to How to exclude (ignore) android build variants in gradle kts

It wasn’t work because of missing line in top-level build.gradle.kts this line:

classpath("com.android.tools.build:gradle:4.0.1")

Categories
discuss

Put elements at the begginning of an array with filter and sort – javascript

I have an array of objects where I want to find certain elements and put them in the beginning or the array. I started doing it by using the find function and it worked but now because there can be more than one element I switch to filter function however, now it stopped working, how can I fix this?

Input example:

colors= [
   {name: "green", popular: true},
   {name: "yellow", popular: false},
   {name: "red", popular: true},
   {name: "black", popular: true},
   {name: "red", popular: true}
]

Function:

sort(colors) {
    let red= colors.filter(color=> colors.name === "red")

    if(red){
        colors.sort(function(x,y){ return x == red? -1 : y == red? 1 : 0; });
    }

    return colors
}

Expected Output:

colors= [
   {name: "red", popular: true},
   {name: "red", popular: true},
   {name: "green", popular: true},
   {name: "yellow", popular: false},
   {name: "black", popular: true}
]

By using filter red variable returns an array instead of an object like with find

Answer

You could just sort red parts to top.

const
    colors= [{ name: "green", popular: true }, { name: "yellow", popular: false }, { name: "red", popular: true }, { name: "black", popular: true }, { name: "red", popular: true }];

colors.sort((a, b) => (b.name === "red") - (a.name === "red"));

console.log(colors);
Categories
discuss

Typescript generics: types ‘T’ and ‘number’ have no overlap error

Consider this example:

function foo<T>(t: T): boolean {
  return t === 1;
}

I get This condition will always return 'false' since the types 'T' and 'number' have no overlap..

The error goes away if I change it to:

function foo<T extends any>(t: T): boolean {
  return t === 1;
}

I thought T could be any by default, so why did I need extends any? Without extends any, what type does TS expect T to be?

Edit, actual function:

function cleanObj<T>(
  obj: ObjectOf<T>,
): ObjectOf<T> {
  const newObj = {};
  for (const k of Object.keys(obj)) {
    if (obj[k] !== null && typeof obj[k] !== 'undefined' && obj[k] !== false) {
      newObj[k] = obj[k];
    }
  }

  return newObj;
}

Answer

Partially taken from https://github.com/microsoft/TypeScript/issues/17445 :

Consider your original function:

function compare<T>(obj: T): boolean {
  return obj === 1;
}

if it would be allowed to compare anything to T we could also write:

function compare<T>(obj: T): boolean {
  return obj === 'some-string-thats-definitely-not-obj';
}

If you use that function inside of some if, you could potentially create unreachable code that won’t throw an error.

This is why typescript requires you to explicitely tell it that T can be any, which is obviously unsafe for the above reason.

Source: stackoverflow
Text is available under the Creative Commons Attribution-ShareAlike License; additional terms may apply. By using this site, you agree to the Privacy Policy, and Copyright Policy. Content is available under CC BY-SA 3.0 unless otherwise noted. The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 © No Copyrights, All Questions are retrived from public domain..