
Experienced Full Stack Developer passionate about new technologies, leading teams to deliver
innovative software solutions, and continuously learning to integrate cutting-edge technologies
for revolutionary results.
Inside Sales Executive
CEEKAY SHIPPING - LINEOperations Coordinator
Eagle InbritVolunteer
Rotary InternationalSenior Software Engineer (Mobile Team)
Proseon TechnologiesLead Flutter Developer
Rockers TechnologiesMobile Team Lead (SDE-3)
Signzy Technologies
VSCode

WebStorm
.png)
Docker
.png)
Jenkins

Github

Bitbucket

Postman

Fiddler

Tomcat

Github Actions

Bash

AWS
Figma

Trello

Zeplin

Adobe XD

SVN
Could you help me understand more about the background by giving a brief introduction? Okay, so I've been working as a mobile app developer since 2017. I started as a mobile app developer only. I began working with Android and beneath you, so after that, I moved to Flutter after a few years, and that particular switch was also inspired by the management, which was rewriting the existing native Android application to Flutter. We were covering both iOS and Android platforms with that. So that was the initial switch to Flutter. After that, I have worked with a service provider company.
The best way to manage a complex state that includes user interaction, data fetching, and local persistence is basically dependent on the type of application we are building. A complex state is basically including many types of data included in a single state. Also, handling user interaction inside a state is a complex part. However, I would prefer using Flutter Bloc or QBuild because they allow us to have many freedoms and control over the events and the states that we are going to have. Also, local persistence, I would basically try to use preferences for simple applications, but there are other complex persistent storage libraries also available, like SQLite, and Hive. Hive is basically dynamic storage. It can store any serializable data in any format. So, yeah.
I would optimize a Flutter app's network request by, basically, clubbing all the requests using the future APIs or trying to prioritize the recent events. Like, let's say, if we are dealing with an application that calls an API on user click, so I would prefer or I would prioritize the recent click rather than handling all the requests. So, basically, debounce any events.
I try to keep the logic away from the widgets. I basically followed the MVC pattern, but with a slight change where the controller doesn't have any control over the view. It's a mix of MVVM and MVC for me. I try to keep the logic away from the widgets. The domain knowledge is kept inside the model. Any processor or any services that I have, I create a manager class, a manager or a controller class, basically, that processes the data, stores it in the model, and whenever the data is updated, an observable data reference is forwarded to the widget, so the widget updates directly. I generally use the block builder from the Flutter block package.
I would prefer using third-party libraries with verified uploaders only, mostly from the Flutter or that team. There are some other verified uploaders as well, like Symphony, which creates a few custom UI libraries, such as charting libraries and everything. I review third-party libraries first, even if they are uploaded by a verified uploader. I try to go through the source code as much as possible. Since Flutter is mostly open source, I can review everything. That's how I try to manage the security part of package checks. Another thing I do is check the number of updates a particular package is getting. For complex packages, I try to find any packages that are recently updated. And I look for packages that are updated with the latest Flutter upgrade as well. So, any recent updates with the Flutter SDK should be reflected in that package.
The refactoring application to improve performance and stability using the Flutter block package. Basically, I would try to separate out all the states and events. I would try to remove any interaction directly applied on the widgets, and instead, I would just fire specific events to be captured by the block. Then the state can be handled by mapping events to states, with a method responsible for converting that particular event to the state. The block builder will update the particular widget whenever the state is finally updated. That's how I would refactor a Flutter application. I will try to start that particular application with the Flutter block as soon as possible rather than having to refactor it later on. So yeah.
This is in Flutter block package. What debug strategy would you suggest to ensure that the load data event results in the correct state? I am not sure what load data method or is a method is going to do in here? Let me check. Okay. So my data block is we are adding an event on my data block to load the data. Okay. To ensure the correct state, I would suggest, just going through the entire event to state conversion. So I'm going to the block's map event to state method. I would check for the particular event where switch case or if statement is there. I will go through the following method or implementation for converting that particular event, processing that event, and finalizing or updating the new state before using it. So two points are that where I will receive the event, which is in block listener or block data, and where the state and state data are being updated. I will check for any anomalies or inconsistencies in those areas.
Most of the time, I've seen a Flutter performance bottleneck is due to widget renders with heavy API calls or very frequent rebuilds. For starters, I would try to limit the rebuilds of that particular widget. I try to understand why it's rebuilding, what's causing that particular loop. Try to resolve that problem and mostly resolve the multiple rebuilds. If not necessary, I would convert it into a stateful widget with particular events that trigger and create a new widget again instead of having it as a straightforward widget. Those will be my initial implementations, initial changes. The other things I would check is the tools. Performance tools are available with the SDK. Those tools will allow me to check which particular widget is rebuilding or what's happening behind the scenes, like inside memory or CPU function calls. I'll use that to dive deeper into the issue and find the root cause. So, yeah, that's it.
I try to follow the TDD methodology. I create widgets along with their basic tests. I don't go into the entire testing like in TDD, but I try to cover as much as basic criteria for that particular widget before I start working on the logic. Also, I try to cover the business logic as well inside the unit testing. I try to keep them separate so that they can be tested properly, keep them modularized. And the other thing is I would use mockable APIs, mockable plugins, that allow me to mock particular widgets with test data. So, that's it.
I'd suggest a strategy to enhance prototype CICD pipeline sharing screen line code and then affect overall screenings. The expected strategy here depends on the existing strategy. However, in my recent work with custom CICD pipelines, I've found that streamlining deployment can be achieved by implementing a continuous testing approach. To do this, every code commit to the repository should go through Flutter Links, which should run unit tests once the test is passed. If unit tests pass, it should then run all integration tests if available in the pipeline. If not, we can skip it. Integration tests can be done manually or automated using tools like Maestro, a mobile testing tool. Other than that, passing all tests is the first task. If the tests pass, we build the APKs or iOS files or anything we want. If any test fails, we won't build and will instead fill that pipeline and ask the developer to fix the issue.
I would utilize additional state management solution like provider. I've been using provider alongside Flutter bloc. I've been using it as a block provider in some states where we cannot pass blocks directly, or we cannot create a new instance of a particular block in some cases. So I assign it to a provider, and I use the provided provider reference in children widgets in some other files to access that particular block. A reward port works the same. The working of provider and reward are similar, so I use the same approach.