Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lag when soft keyboard is opened / closed in a chat #1569

Open
kidfromjupiter opened this issue Jan 24, 2025 · 2 comments
Open

Lag when soft keyboard is opened / closed in a chat #1569

kidfromjupiter opened this issue Jan 24, 2025 · 2 comments
Labels
bug Something isn't working

Comments

@kidfromjupiter
Copy link

kidfromjupiter commented Jan 24, 2025

Bug Description

In ChatView, ( essentially in a room ), when soft keyboard opened/ closed, there is an enormous lag spike when all the widgets are being rebuilt. Adding resizeToAvoidBottomInset: false to the parent Scaffold fixes this but inputfield is now covered by keyboard, not to mention the bottom half of the chat.
Tested on Android, Tab s9+ and A55. The faster tab gives better framerates but still noticeable stutter.

This is a pretty well documented issue in flutter I think but as a chat application that requires constant opening and closing of keyboard this kind of takes away from the UX imo.

Steps to Reproduce

  1. Go to any chat
  2. Touch input field and let keyboard Open

Expected Behavior

No stutter, keyboard opens fluidly

App Version

Self compiled from commit 6f18f716 with flutter 3.27.1. Also present in release 1.23.0

Additional Platform Information

Android, A55, Tab s9+

Additional Context

I only recently started learning flutter but is there a way to move the whole screen "up" without rebuilding? Another possible workaround would be to add an element which matches the height of the keyboard exactly which would move the chats upward, then somehow "detaching" the input field and moving it above the keyboard as well.

@kidfromjupiter kidfromjupiter added the bug Something isn't working label Jan 24, 2025
@kidfromjupiter
Copy link
Author

kidfromjupiter commented Jan 25, 2025

Is there a way to avoid all these expensive message widget rebuilds. As you can see below, there is a potential of 35ms saving off of a 175ms frame ( in debug mode so actual absolute savings will be less but still a 20% reduction in frame time ). The average kb opening and closing frametime is around 18 - 27ms on my mid tier device ( samsung A55 ) so at the worst, it'll only increase frame times by 3-5 ms.

Another thing to note is that even while, the previous screen is not visible, it seems to be still completely rebuilt. This seems to be the biggest culprit of UI jank since it takes around 60ms of a 175ms render. So around 34%

Image

@kidfromjupiter
Copy link
Author

kidfromjupiter commented Feb 2, 2025

After literal days of debugging, I've found where the issue originates. All widgets rebuild when a keyboard opens because in themes.dart, there's these lines

   static bool isColumnMode(BuildContext context) =>
      isColumnModeByWidth(MediaQuery.of(context).size.width);

  static bool isThreeColumnMode(BuildContext context) =>
      MediaQuery.of(context).size.width > FluffyThemes.columnWidth * 3.5;

Commenting these out and replacing them with appropriate boolean values ( for your respective test device. I tested with a phone and so both needed to be false ) gives you perfect framerates with no excessive rebuilds. I added debug statements in many build methods to see when they were rebuilt and before this change,

I/flutter (26273): [Matrix] Themebuilder: rebuilding
I/flutter (26273): [Matrix] MaterialApp.router: rebuilding
I/flutter (26273): [Matrix] child is different
I/flutter (26273): [Matrix] different child: Router<Object>
I/flutter (26273): [Matrix] Matrix: rebuilding
I/flutter (26273): [Matrix] ChatListController: rebuilding
I/flutter (26273): [Matrix] Chatlistview: building

And after the change, nothing when opening / closing keyboard.

So I guess this boosts performance by an absolute crapload since you're not wasting time rebuilding everything but now I gotta find a way to refractor these 2 variables somewhere less... expensive. Putting these variables here might have seemed like a great idea at the time but when a lot of widgets and children reference this down the tree, essentially they're all depending on MediaQuery, so they'll rebuild till kingdom come.

  //static bool isColumnMode(BuildContext context) =>
  //    isColumnModeByWidth(MediaQuery.of(context).size.width);
  static bool isColumnMode(BuildContext context) => false;

  //static bool isthreecolumnmode(buildcontext context) =>
  //    mediaquery.of(context).size.width > fluffythemes.columnwidth * 3.5;

  static bool isThreeColumnMode(BuildContext context) => false;

This is my current "fix". Now,

This will break all responsiveness so while it's a nightmare for web, its manageable for mobile

I'll be looking to creating something like a Provider for MediaQuery so that this doesn't happen each time keyboard is opened yet remaining responsive-ness

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant