Spec recreated when the visibility of the soft keyboard change
See original GitHub issue- I have searched existing issues and this is not a duplicate
Version
implementation 'com.facebook.litho:litho-core:0.8.0'
implementation 'com.facebook.litho:litho-widget:0.8.0'
compileOnly 'com.facebook.litho:litho-annotations:0.8.0'
annotationProcessor 'com.facebook.litho:litho-processor:0.8.0'
Issues and Steps to Reproduce
I have a Spec that create a Recycler that might contains multiple components of different types (text, checkbox, radio buttons, etc.).
Here is the main spec :
@LayoutSpec
public class LithoActivitySpec {
@OnCreateLayout
static ComponentLayout onCreateLayout(final ComponentContext c, @Prop FormDescription formDescription,
@Prop FormFieldSpec.FormFieldListener listener,
@Prop ButtonSpec.ButtonClickListener buttonListener) {
final RecyclerBinder recyclerBinder = new RecyclerBinder.Builder()
.layoutInfo(new LinearLayoutInfo(c, OrientationHelper.VERTICAL, false))
.build(c);
final Component recycler = Recycler.create(c)
.binder(recyclerBinder)
.build();
bindDescriptionToRecycler(c, recyclerBinder, formDescription, listener);
return Column.create(c)
.child(Button.create(c)
.text("validate")
.listener(buttonListener))
.child(recycler)
.build();
}
private static void bindDescriptionToRecycler(ComponentContext c, RecyclerBinder recyclerBinder,
FormDescription formDescription,
FormFieldSpec.FormFieldListener listener) {
List<RenderInfo> renderInfos = new ArrayList<>();
for (ElementValue elementValue : formDescription.elementValues) {
ElementValueType elementValueType = elementValue.getElementValueType();
renderInfos.add(ComponentRenderInfo.create().component(
FormField.create(c)
.text(elementValueType.getName())
.dataType(elementValueType.getElementValueDataType())
.elementValueTypeId(elementValueType.getId())
.listener(listener)
.build())
.build()
);
}
recyclerBinder.insertRangeAt(0, renderInfos);
}
...
}
And here is the spec that will build the correct component depending of the DataType:
@LayoutSpec
public class FormFieldSpec {
public static final int TEXT_SIZE = 16;
@OnCreateLayout
static ComponentLayout onCreateLayout(ComponentContext c,
@Prop String text,
@Prop ElementValueDataType dataType,
@Prop String elementValueTypeId,
@Prop FormFieldListener listener) {
return Row.create(c)
.paddingDip(YogaEdge.ALL, 16)
.child(Text.create(c)
.text(text)
.verticalGravity(VerticalGravity.CENTER)
.textColor(ContextCompat.getColor(c, android.R.color.tab_indicator_text))
.textStyle(Typeface.BOLD)
.textSizeSp(TEXT_SIZE)
.isSingleLine(false)
.widthPercent(33.0f))
.child(getValueComponentLayout(c, dataType, elementValueTypeId, listener))
.build();
}
private static ComponentLayout getValueComponentLayout(ComponentContext c,
ElementValueDataType dataType,
String elementValueTypeId,
FormFieldListener listener) {
Component.Builder builder;
switch (dataType.getType()) {
case DATE: builder = FormFieldDate.create(c)
.elementValueTypeId(elementValueTypeId)
.allowFuture(((DateDataType) dataType).isFuturePossible())
.withTime(((DateDataType) dataType).isWithTime())
.listener(listener);
break;
case RADIO_BOOLEAN: builder = FormFieldRadioBoolean.create(c)
.elementValueTypeId(elementValueTypeId)
.listener(listener)
.valueTrue(((RadioBooleanDataType) dataType).getValueTrue())
.valueFalse(((RadioBooleanDataType) dataType).getValueFalse());
break;
case CHECK_BOOLEAN: builder = FormFieldCheckBoolean.create(c)
.elementValueTypeId(elementValueTypeId)
.listener(listener)
.valueTrue(((CheckBooleanDataType) dataType).getValueTrue())
.valueFalse(((CheckBooleanDataType) dataType).getValueFalse());
break;
case STRING_LIST: builder = FormFieldVdoList.create(c)
.elementValueTypeId(elementValueTypeId)
.listener(listener)
.allowCustomValues(((StringListDataType) dataType).allowCustomValues())
.rootOption(((StringListDataType) dataType).getRootOption());
break;
default: builder = FormFieldString.create(c)
.elementValueTypeId(elementValueTypeId)
.listener(listener);
}
return builder.buildWithLayout();
}
...
}
So if I have a Recycler that looks something like this:
Date
Radio
String
Check
String
Everytime I open or hide the keyboard, all my fields became empty. I set a breakpoint on the LithoActivitySpec#onCreateLayout()
and I saw that everytime the keyboard change its visibility, this method is called.
Is it a bug or something I’m doing wrong on my side? Is their a onSaveInstanceState or something simillar to handle this?
Expected Behavior
I expect the opening/closing of the soft keyboard not triggering the onCreateLayout
of my spec.
Side note
I’ve written this issue first on StackOverflow but I’m wondering what is the best place to post issues as this one? I see more traffic here on GitHub than on SO.
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (3 by maintainers)
Top GitHub Comments
adjustResize will change the size of your LithoView. That means that a new layout needs to be computed for the new size and that’s why your onCreateLayout is called again. This behaviour is completely expected. Is it causing a problem for you?
Added docs and an example codelab to show how to save and restore state on app configuration change: https://github.com/facebook/litho/tree/master/codelabs/save-state-rotation