DEV Community

rymrimi777-rgb
rymrimi777-rgb

Posted on

I Thought AI Could Handle Everything Then I Tried Adding a Rabbit


A small animated character, an unexpected performance problem, and a reminder that AI should assist developers, not replace their judgment.
Artificial intelligence has become an incredible companion for developers
It can help us understand unfamiliar concepts, explore solutions, debug errors, and turn ideas into working features. It can make development faster and help us overcome technical obstacles.
But there is a difference between getting AI to generate code and understanding whether that code is actually the right solution for your project.
I learned this while working on a small feature for my app
Surprisingly, it started with a rabbit🐇

1. The Idea: A Little Rabbit Inside My Notebook

While working on Notebook, I wanted to make the application feel more personal by adding an animated rabbit character.
I found a pixel-art asset called 32x32 FREE Pixel Bunnies – Animated NPC by Last tick on itch.io
The asset contained different rabbit animations, making it a good starting point for the character I had in mind
My goal was not simply to place an image somewhere on the screen. I wanted the rabbit to move naturally, display different animations, and become part of the application's visual experience.
I thought the implementation would be relatively straightforward.
I already had the asset. I had a clear idea of what I wanted. And I had an AI assistant that could help me implement it
So, naturally, I expected things to go smoothly.
I was wrong about one important detail.

2. My First Assumption: AI Would Handle the Sprite Sheet Automatically

I initially assumed that if I provided the ready-made sprite sheet to AI, it would understand how the animations were organized and handle the implementation automatically.
I expected it to identify the relevant frames, separate the movements, and produce the animation behavior I wanted
Instead, the result did not match my expectations
The rabbit's different poses and movements were not organized or displayed in the way I had imagined.
I realized that giving AI an asset was not the same as giving it a complete understanding of how I wanted that asset to behave
A sprite sheet is not just an image. It is a collection of frames that must be interpreted correctly
Depending on its layout, the implementation may need to account for frame dimensions, frame order, animation sequences, and playback timing
Without a clear understanding of those details, an implementation can produce an unexpected result even when the original asset is perfectly usable.

So, I changed my approach.

Instead of relying on AI to handle everything automatically, I decided to select the movements I actually needed and separate them into individual animation sequences
I wanted to control which frames belonged to each movement and how the rabbit would behave inside the application.
This was my first lesson:
Having the right asset is only the beginning. Understanding how to integrate it is part of the engineering work.

3. My Second Assumption: Increasing the Speed Would Fix the Lag

After working on the animation, I encountered another problem.
The application became noticeably less smooth on my phone.
The rabbit was supposed to make the experience more enjoyable, but the animation introduced lag and affected the application's responsiveness
My first thought was simple: perhaps the animation was too slow.
I assumed that increasing the playback speed might solve the problem.
However, I eventually realized that animation speed and rendering performance are two different things 

Increasing the speed changes how quickly frames are displayed. It does not necessarily reduce the amount of work the application performs to render those frames.
If the application is rebuilding too much of the interface, repeatedly decoding images, or running unnecessary animation processes, changing the frame timing alone will not address the underlying cause
A faster animation can still be inefficient
And a slower animation can still consume unnecessary resources.
The visible symptom is not always the actual problem.

That realization changed the way I approached the issue.

Instead of continuing to adjust the animation blindly, I needed to consider how the feature was implemented and how it interacted with the rest of the application.

4. Looking Beyond the Animation

An animated character might look like a small visual feature, but implementing it efficiently involves several different considerations.
In my case, there were three important areas to investigate.

Unnecessary widget rebuilds

Flutter uses a widget-based architecture, and rebuilding widgets is a normal part of how the framework works
The problem is not that rebuilds happen. It is when updates trigger more work than necessary

If setState() is used in a way that rebuilds a larger portion of the interface for every animation update, it can introduce avoidable overhead.
For an animation with frequently changing frames, keeping updates localized becomes particularly important.

Image loading and memory usage

A sprite sheet can contain many individual frames, and animations may involve several image assets.
Loading and decoding images can require processing time and memory. Repeating unnecessary work can affect responsiveness, especially on devices with limited resources


Image caching and appropriate preloading can help, but loading every possible frame into memory without considering the available resources is not automatically the best solution.
The goal is to reuse resources efficiently while keeping the animation responsive.

Timers and animation lifecycle

Animations often rely on timers, animation controllers, or other mechanisms to schedule updates.

If these continue running when they are no longer needed, they can waste resources.

Repeatedly creating animation controllers or timers without managing their lifecycles correctly can also introduce unnecessary work and unpredictable behavior.

These details may not be visible in a screenshot, but they can make a difference when the application is running.

5. The Technical Changes I Focused On

Once I understood the different areas involved, I started focusing on making the animation more efficient.

Rather than treating the rabbit as an isolated image, I approached it as a component with its own responsibilities.

Isolating animation updates

I used ValueListenableBuilder and AnimatedBuilder within a dedicated RabbitWidget to keep animation-related updates localized.

The objective was to avoid triggering unnecessary rebuilds of unrelated parts of the interface.

These tools do not automatically guarantee better performance, but they provide ways to structure updates more selectively.

Improving image handling

I used precacheImage and Flutter's image cache to improve image availability and reduce unnecessary loading work.

Preloading images can help prevent delays when a frame is needed. However, it must be balanced against memory usage, especially when an animation contains many frames
Optimization is not simply about loading everything in advance. It is about making sensible decisions based on the resources the application needs.

Adjusting frame timing

I considered the timing required for different types of movement rather than assuming that increasing the playback speed would solve the problem
Different animations can have different timing requirements.

A resting animation does not need to behave like a walking animation, and the frame rate should support the intended movement rather than introduce unnecessary updates.

Managing animation lifecycles

I paid attention to the lifecycle of timers and animation controllers, making sure they could stop when they were no longer needed and be disposed of appropriately.
The goal was to avoid unnecessary background activity and prevent animation processes from continuing beyond their intended lifetime.

Preserving the pixel-art style

I also used RepaintBoundary where appropriate to isolate the rabbit's painting from surrounding widgets.

For the visual style, I used FilterQuality.none to preserve the crisp edges of the pixel art instead of introducing unwanted smoothing.

These choices addressed different aspects of the implementation: widget updates, image handling, lifecycle management, rendering, and visual quality.

No single technique is a universal solution for animation lag. The right approach depends on the actual bottleneck.

That is why understanding the implementation matters more than blindly applying optimization techniques.

6. What This Experience Taught Me About AI-Assisted Development

This experience was not about discovering that AI is bad at programming.
It was about understanding the limitations of relying on generated solutions without evaluating their behavior in the context of a real application.
AI can generate code that looks reasonable. It can suggest useful APIs and help explore different implementations.
But it does not automatically know every constraint of your project.

It may not understand exactly how you want an animation to behave, how much memory your target device can comfortably use, or which parts of your interface should update when a frame changes.

Even when a suggested implementation is technically valid, it may not be the most appropriate solution for your application.

That is where the developer's responsibility begins.

I still need to ask questions such as:

  • Does this implementation match the behavior I actually want?
  • Am I rebuilding more widgets than necessary?
  • Could image loading or decoding affect responsiveness?
  • Are timers and animation controllers managed correctly?
  • Does this feature behave properly when navigating between screens?
  • Have I tested the result on the device where the application will be used?

These questions cannot be replaced by simply asking AI to generate another version of the code.

They require observation, reasoning, and testing.

7. AI Is a Companion, Not Your Brain

I believe AI can be one of the most useful tools available to developers
It can help us learn faster, explore unfamiliar technologies, understand errors, and approach problems from different perspectives
I use it as a tool to support my development process, not as a substitute for understanding what I am building.
There is nothing wrong with asking AI for help.
The important thing is to remain involved in the decisions that shape your project.
If a generated solution does not match your requirements, question it
If a feature works but makes the application slower, investigate why
If a suggested optimization sounds convincing, verify whether it actually addresses the problem.

And if you discover that your original assumption was wrong, change your approach.

That is not a failure. It is part of software development.
Sometimes, the most valuable thing you learn from an implementation is not how to write the code, but how to recognize when the code needs a different approach.

Final Thoughts

The rabbit was supposed to be a small addition to 1734 Notebook.
Instead, it made me think more carefully about sprite sheets, animation timing, widget rebuilds, image resources, and performance
I initially expected AI to interpret the asset and organize its animations automatically. When the result did not match my expectations, I took a more deliberate approach to selecting and separating the movements

Later, when the application became less responsive, I assumed increasing the animation speed would help. That assumption reminded me to look beyond the visible symptom and consider the work happening underneath.
The experience reinforced something I want to carry into every project I build:

AI can help you write the code, but you are still the engineer responsible for the result.

  • use it to explore possibilities, but do not stop thinking
  • Use it to accelerate your work, but do not skip testing.
  • Use it to solve problems, but make sure you understand the solutions you choose

Because the goal is not to generate code as quickly as possible.
The goal is to build software that works well, respects its users, and remains maintainable as it grows.
And sometimes, a little pixel-art rabbit is enough to remind you of that


I'd love to hear about your experience: Have you ever asked an AI assistant to implement a feature that looked simple but turned into a much bigger engineering challenge? What did you learn from it?

Credits

Rabbit sprite asset: 32x32 FREE Pixel Bunnies – Animated NPC by Last tick
Please check the asset's current licence and attribution requirements before publishing.

Top comments (1)

Collapse
 
ace_bl profile image
Ace •

A little pixel rabbit hopping around a notebook app is such a lovely touch, and this is a great story about where the real engineering lives. Choosing the exact frames yourself and splitting them into separate animation sequences is the kind of judgment no prompt can hand you. Thanks for being so honest about your assumptions along the way. What's the rabbit's favorite thing to do in the app now that it runs smoothly?