codeslubber
02/28/2020, 7:25 PMTextField
before, but with a TextFieldInput
that was in a state var, e.g. state { TextFieldInput("") }
) But I already have a state so I wanted to put the TextFieldInput into that instance, so, something like state { TimerState() }
where TimerState has the TextFieldInput in it, but not having much success with that.
The other possibility (part of why I am posting) is way back during early MVC days there was another pattern called PAC. One of the main distinctions is PAC had hierarchies of components, and each component might have its own Abstraction (model) and controller. Should I do that? Make the text input a component? and if so, how do I bubble the edit result up to the enclosing component?Leland Richardson [G]
02/28/2020, 8:00 PMBut I already have a state so I wanted to put the TextFieldInput into that instance, so, something likeWhat was unsuccessful about this?where TimerState has the TextFieldInput in it, but not having much success with that.state { TimerState() }
Leland Richardson [G]
02/28/2020, 8:01 PMvalue
/ onValueChange
parameters be passed through to the lower level componentLeland Richardson [G]
02/28/2020, 8:02 PM@Composable fun FancyTextField(value: String, onValueChange: (String) -> Unit) {
TextField(value, onValueChange)
}
codeslubber
02/28/2020, 8:06 PMMutableState<TextFieldInput>
. Not sure why .If I have a composable function, it all works, but then when I click submit, how should I get the value back into the outer view? I saw examples that have you pass the var you want it assigned to into the submethod?Leland Richardson [G]
02/28/2020, 8:09 PMcodeslubber
02/28/2020, 8:15 PMclass TimerState(hours:TimeDigit = TimeDigit(0), minutes:TimeDigit = TimeDigit(0), seconds:TimeDigit = TimeDigit(0)) {
var currentStatus:String = {
"$hours:$minutes:$seconds"
}()
var amountOfSkinInput = TextFieldValue("")
var amountOfSkin:Int = 50
}
and this does not work. I think because the input field is not a `MutableState<TextFieldValue>`right? but I can’t nest state {}
so?codeslubber
02/28/2020, 8:17 PM@Composable
fun numberInput(startAt:Int, range: IntRange, units: String){
val state = state { TextFieldValue(text = "") }
TextField(
value = state.value,
//modifier = Border(Dp.Hairline, Color.Gray),
onValueChange = {
state.value = it
},
keyboardType = KeyboardType.Number,
textStyle = TextStyle(fontSize = 64.sp)
)
Button(onClick = {
if (!range.contains(state.value.text.toInt())){
Log.d("VALIDATOR", "Out of range!")
} else {
}
}){
Text("Submit")
}
}
but then on submit, I would have to assign this value back to the field in the outer view state.codeslubber
02/28/2020, 8:17 PMLeland Richardson [G]
02/28/2020, 8:30 PMLeland Richardson [G]
02/28/2020, 8:31 PMLeland Richardson [G]
02/28/2020, 8:31 PMnumberInput
what we call a “controlled” composableLeland Richardson [G]
02/28/2020, 8:31 PMLeland Richardson [G]
02/28/2020, 8:32 PMLeland Richardson [G]
02/28/2020, 8:34 PM@Composable
fun numberInput(
value: Int,
onValueChange: (Int) -> Unit,
startAt:Int,
range: IntRange,
units: String
) {
TextField(
value = value.toString(),
onValueChange= {
// TODO: validation here
onValueChange(it.toInt())
}
)
}
Leland Richardson [G]
02/28/2020, 8:35 PMLeland Richardson [G]
02/28/2020, 8:35 PMstate
will only invalidate the composition when the value itself is setcodeslubber
02/28/2020, 8:35 PMcodeslubber
02/28/2020, 8:35 PMLeland Richardson [G]
02/28/2020, 8:36 PMstate { TimerState() }
and you mutate a property on the TimerState
instance itself, there is no way compose will recognize that and recomposeLeland Richardson [G]
02/28/2020, 8:36 PM@Model
Leland Richardson [G]
02/28/2020, 8:36 PMLeland Richardson [G]
02/28/2020, 8:36 PM@Model
class TimerState(hours:TimeDigit = TimeDigit(0), minutes:TimeDigit = TimeDigit(0), seconds:TimeDigit = TimeDigit(0)) {
var currentStatus:String = {
"$hours:$minutes:$seconds"
}()
var amountOfSkinInput = TextFieldValue("")
var amountOfSkin:Int = 50
}
codeslubber
02/28/2020, 8:36 PMLeland Richardson [G]
02/28/2020, 8:37 PMcodeslubber
02/28/2020, 8:37 PMcodeslubber
02/28/2020, 8:37 PMcodeslubber
02/28/2020, 8:38 PMLeland Richardson [G]
02/28/2020, 8:38 PMdata class TimerState(...)
and then have var timerState by state { TimerState(…) }
Then when you want to have an invalidation, you can do timerState = timerState.copy(…)
Leland Richardson [G]
02/28/2020, 8:39 PMmutableStateOf
codeslubber
02/28/2020, 8:39 PMLeland Richardson [G]
02/28/2020, 8:39 PMclass TimerState(hours:TimeDigit = TimeDigit(0), minutes:TimeDigit = TimeDigit(0), seconds:TimeDigit = TimeDigit(0)) {
val currentStatus:String = {
"$hours:$minutes:$seconds"
}()
var amountOfSkinInput by mutableStateOf("...")
var amountOfSkin:Int = 50
}
Leland Richardson [G]
02/28/2020, 8:39 PMamountOfSkinInput
and since it is backed by a MutableState
instance, it will be observed by composecodeslubber
02/28/2020, 8:39 PMLeland Richardson [G]
02/28/2020, 8:40 PMvar
when using compose unless it is a State
property delegate, or a property on a @Model instanceLeland Richardson [G]
02/28/2020, 8:41 PMcodeslubber
02/28/2020, 8:41 PMLeland Richardson [G]
02/28/2020, 8:41 PMstate
and immutable value types onlyLeland Richardson [G]
02/28/2020, 8:41 PMLeland Richardson [G]
02/28/2020, 8:41 PM@Model
also has its uses, and others might disagree with meLeland Richardson [G]
02/28/2020, 8:42 PMLeland Richardson [G]
02/28/2020, 8:42 PMLeland Richardson [G]
02/28/2020, 8:43 PMLeland Richardson [G]
02/28/2020, 8:44 PMTextFieldValue
overload and not the String
overload of TextField
?codeslubber
02/28/2020, 8:44 PMLeland Richardson [G]
02/28/2020, 8:44 PMcodeslubber
02/28/2020, 8:45 PMEditorModel
in there and then found TextFieldValue
was the replacementcodeslubber
02/28/2020, 8:46 PMLeland Richardson [G]
02/28/2020, 8:47 PMLeland Richardson [G]
02/28/2020, 8:48 PMcodeslubber
02/28/2020, 8:53 PMcodeslubber
02/28/2020, 8:54 PMLeland Richardson [G]
02/28/2020, 8:58 PMcodeslubber
02/28/2020, 9:33 PMLeland Richardson [G]
02/28/2020, 9:37 PMLeland Richardson [G]
02/28/2020, 9:39 PMLeland Richardson [G]
02/28/2020, 9:39 PMhistory
one has some interesting use cases i thinkcodeslubber
02/28/2020, 9:51 PMcodeslubber
02/28/2020, 9:51 PMcodeslubber
02/28/2020, 9:51 PMcodeslubber
02/28/2020, 10:07 PMLeland Richardson [G]
02/28/2020, 10:20 PMcodeslubber
02/28/2020, 10:37 PMcodeslubber
02/28/2020, 10:38 PMcodeslubber
02/28/2020, 10:38 PMcodeslubber
02/28/2020, 10:39 PMcodeslubber
02/28/2020, 10:39 PMLeland Richardson [G]
02/28/2020, 10:41 PMcodeslubber
02/28/2020, 10:45 PMcodeslubber
02/28/2020, 10:45 PMcodeslubber
02/28/2020, 10:46 PMcodeslubber
02/28/2020, 10:47 PMcodeslubber
02/28/2020, 11:26 PMcodeslubber
02/28/2020, 11:26 PMLeland Richardson [G]
02/28/2020, 11:26 PMcodeslubber
02/28/2020, 11:27 PMcodeslubber
02/28/2020, 11:27 PMLeland Richardson [G]
02/28/2020, 11:28 PMLeland Richardson [G]
02/28/2020, 11:28 PMLeland Richardson [G]
02/28/2020, 11:29 PMcodeslubber
02/28/2020, 11:30 PMcodeslubber
02/28/2020, 11:30 PMLeland Richardson [G]
02/28/2020, 11:31 PMcodeslubber
02/28/2020, 11:31 PMcodeslubber
02/28/2020, 11:31 PMLeland Richardson [G]
02/28/2020, 11:31 PMcodeslubber
02/28/2020, 11:31 PMLeland Richardson [G]
02/28/2020, 11:31 PMcodeslubber
02/28/2020, 11:31 PMLeland Richardson [G]
02/28/2020, 11:32 PMcodeslubber
02/28/2020, 11:32 PMLeland Richardson [G]
02/28/2020, 11:32 PMLeland Richardson [G]
02/28/2020, 11:32 PMLeland Richardson [G]
02/28/2020, 11:33 PMcodeslubber
02/28/2020, 11:33 PMcodeslubber
02/28/2020, 11:35 PMRef
either, it’s solution to import it from java.sql is of course wrong…Leland Richardson [G]
02/28/2020, 11:35 PMclass Ref<T>(var value: T)
Leland Richardson [G]
02/28/2020, 11:35 PMLeland Richardson [G]
02/28/2020, 11:35 PMLeland Richardson [G]
02/28/2020, 11:36 PMprivate
to the front of it)Leland Richardson [G]
02/28/2020, 11:38 PMreduce
Leland Richardson [G]
02/28/2020, 11:38 PM@Composable fun <T> reduce(value: T, reducer: (T, T) -> T): T = {
var result = value
var first = false
val ref = remember { first = true; Ref(value) }
if (!first) {
result = reducer(ref.value, value)
}
onCommit { ref.value = result }
return result
}
Leland Richardson [G]
02/28/2020, 11:38 PMcodeslubber
02/28/2020, 11:38 PMref.value = reducer(ref.value, value)
codeslubber
02/28/2020, 11:39 PMcodeslubber
02/28/2020, 11:39 PMLeland Richardson [G]
02/28/2020, 11:40 PMcodeslubber
02/29/2020, 12:01 AMcodeslubber
02/29/2020, 12:02 AMcodeslubber
02/29/2020, 12:02 AMLeland Richardson [G]
02/29/2020, 12:08 AMLeland Richardson [G]
02/29/2020, 12:08 AMLeland Richardson [G]
02/29/2020, 12:08 AMLeland Richardson [G]
02/29/2020, 12:09 AMcodeslubber
02/29/2020, 12:10 AMcodeslubber
02/29/2020, 12:11 AM// in the case of the first run, does this return null.... or do we just pass the value that came in???
@Composable
fun prev(value: T): T? {
codeslubber
02/29/2020, 12:11 AMcodeslubber
02/29/2020, 12:12 AM@Composable val Ambient<T>.current: T
codeslubber
02/29/2020, 12:13 AMcodeslubber
02/29/2020, 12:13 AMLeland Richardson [G]
02/29/2020, 12:13 AMcodeslubber
02/29/2020, 12:14 AMLeland Richardson [G]
02/29/2020, 12:18 AMLeland Richardson [G]
02/29/2020, 12:18 AMLeland Richardson [G]
02/29/2020, 12:18 AMLeland Richardson [G]
02/29/2020, 12:19 AMcodeslubber
02/29/2020, 1:11 AMcodeslubber
02/29/2020, 1:11 AMcodeslubber
02/29/2020, 1:12 AMcodeslubber
02/29/2020, 1:13 AMcodeslubber
02/29/2020, 1:14 AMLeland Richardson [G]
02/29/2020, 1:15 AMLeland Richardson [G]
02/29/2020, 1:15 AMcodeslubber
02/29/2020, 1:25 AMLeland Richardson [G]
02/29/2020, 1:26 AMcodeslubber
02/29/2020, 2:22 AMe: java.lang.IllegalStateException: Backend Internal error: Exception during code generation
Element is unknownThe root cause java.util.NoSuchElementException was thrown at: androidx.compose.plugins.kotlin.compiler.lower.ComposableCallTransformer.irComposableExpr(ComposableCallTransformer.kt:1362)
at org.jetbrains.kotlin.codegen.CompilationErrorHandler.lambda$static$0(CompilationErrorHandler.java:35)
at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:93)
at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm$default(JvmBackendFacade.kt:64)
at org.jetbrains.kotlin.backend.jvm.JvmBackendFacade.doGenerateFilesInternal$backend_jvm(JvmBackendFacade.kt:52)
at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:36)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.doGenerateFiles(KotlinCodegenFacade.java:47)
at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:39)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:638)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:198)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:172)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:56)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:85)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:43)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:104)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:349)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:105)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:237)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:88)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:606)
at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:99)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1645)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:357)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:573)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:834)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:688)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:687)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.util.NoSuchElementException: Collection contains no element matching the predicate.
at androidx.compose.plugins.kotlin.compiler.lower.ComposableCallTransformer.irComposableExpr(ComposableCallTransformer.kt:1362)
at androidx.compose.plugins.kotlin.compiler.lower.ComposableCallTransformer.visitBlock(ComposableCallTransformer.kt:252)
at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitBlock(IrElementTransformerVoid.kt:128)
at org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid.visitBlock(IrElementTransformerVoid.kt:24)
at org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl.accept(IrBlockImpl.kt:52)
codeslubber
02/29/2020, 2:22 AMLeland Richardson [G]
02/29/2020, 3:01 AMjava.util.NoSuchElementException was thrown at: androidx.compose.plugins.kotlin.compiler.lower.ComposableCallTransformer.irComposableExpr(ComposableCallTransformer.kt:1362)This exception happens when the compose runtime module can’t be found on the classpath, or the newer compiler has an older version of compose runtime on the classpath (like dev03). I’m not sure if this is the reason for your issue or not, but can you paste your build.gradle file?
codeslubber
02/29/2020, 3:26 AMcodeslubber
02/29/2020, 3:26 AMdev05
of course…codeslubber
02/29/2020, 3:27 AMapply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.ontometrics.dminder.suntimer"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), '<http://proguard-rules.pro|proguard-rules.pro>'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
compose true
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.ui:ui-framework:0.1.0-dev05'
implementation 'androidx.ui:ui-layout:0.1.0-dev05'
implementation 'androidx.ui:ui-material:0.1.0-dev05'
implementation 'androidx.ui:ui-tooling:0.1.0-dev05'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
codeslubber
02/29/2020, 3:28 AMcodeslubber
02/29/2020, 3:28 AMcodeslubber
02/29/2020, 3:29 AMcodeslubber
02/29/2020, 3:33 AMLeland Richardson [G]
02/29/2020, 3:54 AM