Sprint 4 ‐ App Implementation and Definition - Isarquis/M-viles-Group13 GitHub Wiki
Designed to solve a problem faced by students every semester, UniMarketplace makes buying, selling, renting or bidding on textbooks and academic materials easy. There is no need to rely on scattered social media posts or unreliable word of mouth. Our app brings all these features together in one simple, reliable space where students can earn and save money with their academic materials, while contributing to a more sustainable circular economy by encouraging the reuse of items that would otherwise end up as waste.
To this end, we have developed features that streamline the experience for students, including filtered searches, product categories, geolocation to find nearby items and support for various transaction types, such as buying, renting and bidding. Users can create their own posts, see who posted what, and manage bids directly from their phones to potentially secure the best offer.
We use a freemium model to support the platform. Anyone can post and browse for free, but users can pay to promote their listings to increase their visibility. We also monitor how users interact with the app and use this real-time data to improve the experience continually.
Ultimately, UniMarketplace makes it easier and more efficient for students to exchange materials, save money, and support each other on campus, while reducing unnecessary consumption and waste and promoting a more environmentally conscious culture within the university community.
David Zamora
Code Before Micro-optimization
This performance issue occurs within the map functionality, where nearby products are displayed to the client using custom markers. Every time the user opens or interacts with the map, the app reloads the product data and attempts to display them visually.
The problem originates in the loadNearbyProducts() method inside the NearbyProductsViewModel. This function is triggered each time the map is loaded or refreshed. During its execution, the app loops through nearby products and generates map markers using the _getProductMarkerIcon method, which downloads, decodes, and renders a custom icon from the product’s image URL on every call. This results in repeated expensive operations, leading to high CPU usage and UI hangs when navigating or reopening the map view.

Profiling Before Micro-optimization
1. Time Profiler & CPU Usage
To evaluate the performance bottlenecks associated with rendering custom map icons in the Flutter application, we conducted a set of profiling sessions using Xcode Instruments. The goal was to identify memory usage patterns, CPU load, frame drops, and UI responsiveness issues during the map rendering phase.

2. Memory Usage (Allocations)
We used the Allocations instrument to track how memory usage evolved throughout the lifecycle of the screen. Memory allocation sharply increased when the map was loaded, which aligns with the downloading and decoding of image assets used for custom markers.
The selected timeframe in the image corresponds to the second time the map was opened. Notably, memory increased again, confirming that image processing is repeated rather than reused from a prior session.

3. Hangs & UI Responsiveness
During this same period, UI hangs were recorded. Although not critically severe, they are meaningful enough to indicate a delay in user interaction handling. These hangs occurred precisely during the re-opening of the map, suggesting the CPU was again burdened by repeated image decoding tasks.

4. Animation Hitches
Two hitches were captured by the Animation Hitches instrument. One of them exceeded the acceptable latency and was marked with high severity due to a “Pre-Commit(s) latency.” This type of hitch typically points to the rendering pipeline being blocked before committing a frame to the screen.

5. CPU Profiler with Symbol Resolution Issues
A separate CPU Profiler session was captured later, but unfortunately, symbol resolution failed, and all function names appeared as memory addresses (). However, this recording is still useful for observing the raw CPU load and the relative weight of operations during map rendering. One of the heaviest frames peaked at over 586 Mc (millions of cycles), suggesting a substantial processing cost at that moment.

Micro-Optimization Strategy: Caching Processed Images
The optimization consists of saving processed custom map icons in memory after their first decoding. When the map is rendered again or the user navigates across it, the app will reuse the cached images instead of decoding and rendering them from scratch. This significantly reduces CPU usage, avoids redundant operations, and improves responsiveness and animation smoothness during scroll or pan actions.
Code After Micro-optimization
In the updated implementation of loadNearbyProducts(), we introduced an in-memory cache using a Map<String, BitmapDescriptor> named iconCache. This cache stores each processed image icon only once per execution of the method.
Before creating a new marker, the code now checks if the icon for a product image already exists in the iconCache. If it does, it reuses it directly. If not, it processes the image and stores the result in the cache. This eliminates redundant decoding and rendering operations within the same map session, significantly reducing CPU usage and improving responsiveness.

Profiling After Micro-optimization
1. Time Profiler & CPU Usage
After applying the caching strategy, CPU usage during map rendering remained similar to previous sessions. The processing cycles stayed at roughly the same levels, with no significant reduction in total CPU load observed during map interactions.
2. Memory Usage (Allocations)
Memory behavior remained consistent with earlier profiling sessions. Allocations occurred mostly during the initial load phase, but did not show additional growth in repeated interactions with the map.
3. Hangs & UI Responsiveness
NO UI HANGS were recorded in this session. Unlike before, all user interactions, including map movement and marker rendering, completed without stalling or freezing the interface.
4. Animation Hitches
Two animation hitches were still present, including one that exceeded latency thresholds. These were similar in pattern and duration to the previous profiling session, indicating no improvement in this specific metric.
5. CPU Profiler
The CPU Profiler confirmed that processing intensity remained high in key frames. Despite the optimization, the frame with highest CPU load peaked similarly to prior sessions.
Code Before Micro-optimization
First this code shows the approach that causes the entire widget to rebuild continuously as the user types. Each call to setState() leads to re evaluation of the entire searbar widget, continuous filtering logic executing during input, and redundant rendering and layout passes.

In the original implementation of the SearchBar, the onChanged callback triggers a setState() on every keystroke. This causes the widget to rebuild continuously, even when the user is still typing. This is inefficient and leads to high CPU and GPU usage, especially when the suggestions list is large.
Profiling Before Micro-optimization

For the profiling we use the CPU Profiler, Core Animation Activity, Time Profiler, Leaks, Allocations, and GPU.

The memory allocation analysis revealed that the SearchBar component was generating an excessive number of temporary object allocations over 1.9 million in total, primarily during live text input. Most of these allocations were small and shortlived (16 to 48 bytes), indicating that each keystroke triggered multiple UI rebuilds and list filtering operations without throttling. This behavior caused unnecessary strain on the heap and GPU, leading to performance degradation. The high count of persistent allocations also suggests memory inefficiency, reinforcing the need for micro-optimizations like debouncing to reduce computational and memory overhead.

The Core Animation Activity reveals that the layout and display phases of the rendering pipeline are consuming significant processing time, especially the layout phase, with an average duration of 101.40 μs and a maximum of 5.50 ms. This suggests that layout recalculations are triggered frequently could be for tthe immediate use of setState() inside the onChanged method of the TextField. These constant UI updates lead to inefficient frame rendering and are particularly costly in terms of performance.

This GPU Channel Activity Summary highlights that Fragment processing dominated the GPU usage, accounting for 4.77 seconds out of the total 6.00 seconds, with notable contributions from both the system and the app.The Vertex shader processing was considerably lower, and Compute operations were minimal. Importantly, the CPU to GPU latency for the Runner under Fragment and Vertex tasks hovers around 911.13 μs, indicating nontrivial rendering delays. These values, particularly the max durations, suggest that excessive rerendering is being triggered during user interaction.

The Leaks instrument reveals multiple memory leaks, mostly originating from CFNetwork and grpc libraries, with allocations as small as 16–160 bytes persisting unexpectedly. Many of these leaks involve network-related objects such as CFStreamEndpointImpl, NSMutableArray, and NSOutputStream, suggesting improper cleanup of connections or responses. Notably, there’s also a Flutter-related allocation leak thats dart::PageSpace::AllocatePage, indicating potential issues with widget lifecycle management likely exacerbated by repeated UI rebuilds during typing.

In the profiling results for the SearchBar feature, multiple background threads are actively engaged during text input, particularly those managed under dispatch_queue and Dart Worker labels. These threads are responsible for executing the filtering logic when the user types, ensuring that suggestions are updated in real time. However, as observed in related scenarios, the UI thread and Raster thread show frequent synchronous spikes, especially around CFRunLoopRun and UIUpdateSequenceRun, which are indicative of potential bottlenecks.
Micro-Optimization Strategy: Debounced Search Input
When users type in the search bar, the app normally reacts to every single letter typed, which can make it slower and use more power, especially if there are lots of products to search through. To improve this, so it was added a small delay before the search actually happens. This means the app waits for the user to pause typing before it starts looking for results.
Code after Micro-optiization
The images below show how we added the "debounce" logic to the search bar. This means that instead of searching with every keystroke, the app now waits 300 milliseconds after the user stops typing before it runs the search. The _onSearchChanged function handles this by using a Timer. If the user keeps typing, the timer is canceled and restarted, so we only search when they pause.
![]() |
![]() |
Profiling After Micro-optimization

The total number of allocations was significantly reduced. Although many small allocations persist, the allocation rate dropped to approximately 1.58 million, suggesting that the use of debounce limited the execution of unnecessary logic and helped stabilize transient memory usage.

The fragment time dropped to 4.23 s, and latency increased slightly (~2 ms), but the total GPU time was reduced to 5.22 s, demonstrating that excessive usage was avoided. The more moderate Vertex and Compute usage reinforces the overall improved efficiency.

The average increased to 194.29 μs for layout, but with a lower event count 815 layers. This suggests that although some updates were more costly individually, they occurred much less frequently. This is consistent with the debounce logic, which avoids frequent calls to setState().

Leaks persist, but the pattern repeats less frequently. Although network objects like SocketStream and HostBase exist, multiple redundant instances do not appear, indicating less memory pressure due to fewer rebuilds.

The implementation of debounce logic reduced the frequency of invocations on these key threads. While CFRunLoopRun and MessageLoopDarwin are still present, their intensity has decreased significantly. Heavy-duty operations like flushPaint and drawFrame are better distributed across worker threads like dispatch_root_queue_drain, start_wqthread, and fml::MessageLoopImpl and are less interrupted by input processing, improving responsiveness and reducing visual jitter during typing.
Code Before Micro-optimization
In the original implementation of the LoginPage, the “Remember me” checkbox was managed using a setState() call. Each time the checkbox was toggled, the entire widget subtree was rebuilt, even though the only state change was a single boolean value. This approach introduced unnecessary widget rebuilds and layout recalculations during minor UI interactions.

Such use of setState() for localized changes increases CPU usage and affects performance consistency.
Profiling Before Micro-optimization

The profiling results for the original LoginPage showed over 4.1 million object allocations, with 180,752 persistent instances consuming around 142.5 MiB of memory. A large portion of these were small, short-lived allocations triggered by minor UI updates—most notably, toggling the “Remember me” checkbox. Since this was managed through setState(), it caused unnecessary full widget rebuilds for a single boolean change.

The Leaks analysis revealed a single memory leak of 32 bytes originating from Flutter’s dart::PageSpace::AllocatePage function. While this may appear minor in isolation, its presence suggests a potential inefficiency in widget lifecycle handling or memory allocation tied to repeated rebuilds in the login view.

Notably, operations like CFRunLoopRun, drawFrame, and flushPaint dominate the timeline, indicating that UI rendering and event handling were frequently triggered. This level of activity likely stems from repeated setState() calls caused by toggling the checkbox, which forces unnecessary redraws and layout passes.

The GPU profiling reveals that fragment processing dominated usage, totaling 6.13 seconds, with 2.69 seconds attributed specifically to the Runner. CPU to GPU latency during fragment rendering averaged 1.88 ms, indicating significant rendering delays triggered by simple UI changes like toggling the “Remember me” checkbox.

The Core Animation Activity analysis shows a high frequency of layout and commit operations, with over 20,364 recorded commits and nearly 1,447 layout recalculations. The layout phase alone consumed 130.98 ms with an average duration of 90.52 μs, indicating excessive UI rebuilding.
Micro-Optimization Strategy: ValueNotifier Refactor in LoginPage
To reduce unnecessary widget rebuilds, the state handling of the “Remember me” checkbox was refactored using a ValueNotifier instead of setState(). This change allows only the checkbox row to update when toggled, avoiding full widget tree rebuilds.
Code after Micro-optiization
In the optimized LoginPage, the “Remember me” checkbox was refactored using ValueNotifier and ValueListenableBuilder. This avoids calling setState() and rebuilding the whole widget tree when toggling the checkbox. Instead, only the checkbox row updates, significantly reducing unnecessary layout and rendering operations during minor UI changes.
![]() |
![]() |
Profiling After Micro-optimization

After the introduction of ValueNotifier for managing the checkbox state, the profiling reveals a slight improvement in memory efficiency. The total number of allocations decreased from over 4.17 million to approximately 1.94 million, reflecting a 53% reduction in transient allocations.

Although micro-optimization with ValueNotifier significantly reduced CPU and GPU load, memory leak analysis shows a slight increase in the number and variety of leaked objects. This suggests that while rendering efficiency has improved, retaining some network and framework objects such as CFNetwork and grps.

Unlike the previous profile, which showed constant synchronous spikes in the main thread (UI Thread) and the Raster Thread, this new visualization shows a lower frequency of intense interruptions in rendering and event handling tasks. Although functions such as CFRunLoopRun and fml::MessageLoopDarwin::Run are still present, their relative weight has decreased and is better balanced.

The total fragment processing time has decreased slightly to 5.65 seconds. Additionally, the CPU-to-GPU latency for fragment and vertex tasks for Runner remains below 1 ms, indicating a more efficient rendering response. Together, this suggests that the elimination of unnecessary setState() calls and the adoption of ValueNotifier have reduced the number of unnecessary calls.

Indicates an overall improvement in rendering efficiency, with the total number of render events dropping from over 20,000 to 17,848, reflecting a reduction in unnecessary visual updates. Although the average layout phase duration increased slightly to 103.11 μs,
Code Before Micro-optimization
Initially, the search input triggered the filtering and UI update logic directly with the onSubmitted or onChanged callbacks, causing the entire product list widget to rebuild every time the user typed or pressed the search button. Each call to setState() re-evaluated the product list and filtering logic, leading to repeated computations and UI renders during user input.
This approach caused continuous widget rebuilds even while the user was still typing or interacting with the search bar, resulting in inefficient CPU and GPU usage, particularly noticeable when filtering a large list of products or loading cached data. The immediate state updates and filtering operations led to unnecessary layout recalculations and redundant rendering passes.
Profiling Before Micro-optimization
For the profiling we use the CPU Profiler, Core Animation Activity, Time Profiler, Allocations, and GPU.
The memory profiling data shows that the app is allocating over 1.01 GiB in total, with approximately 143 MiB of persistent allocations. The transient allocations are very high (over 4.6 million), indicating a lot of temporary objects being created during the search interaction. Most of these allocations are likely small in size (common sizes include 16, 32, and 48 bytes), which is typical when the UI rebuilds happen frequently and filtering logic runs on every keystroke.
Taking that into account we could identify that every time the user types or modifies the search term, the app triggers multiple widget rebuilds and runs filtering and sorting logic repeatedly without any throttling. This generates a large number of objects, which can strain the heap and increase garbage collection overhead, ultimately affecting CPU usage and battery life.
The Core Animation profiling shows that the app spends significant time in the layout and display phases, with frequent and sometimes costly recalculations and rendering events. The high number of layout events and their occasional spikes indicate that the UI is being rebuilt excessively, likely due to frequent state changes such as continuous calls to setState during user input. This leads to increased processing time and potential frame rendering delays. These results highlight the need for micro-optimizations like debouncing input and minimizing unnecessary widget rebuilds to reduce the frequency and cost of layout and display operations, ultimately improving app performance and responsiveness.
The GPU profiling data shows that fragment processing dominates the GPU workload, accounting for the majority of the total 16.37 seconds, with the app (Runner) and system (backboardd) both contributing significantly. Vertex processing is much less intensive but still noticeable, with similar contributions from both the app and system. Compute operations consume a minimal amount of time. The average CPU to GPU latency is relatively low but highlights the GPU as a key area for optimization.
The Time Profiler analysis reveals that a significant portion of CPU time is spent within the main thread of the Runner process, especially inside the Core Foundation run loop and message handling system. The heavy presence of calls like __CFRunLoopRun, __CFRunLoopDoSources0, and runloopSourceCallback indicates that the app is frequently processing events and timers, which may be triggered by UI updates or asynchronous tasks. A notable amount of time is also dedicated to the Flutter rasterizer, which handles rendering frames on the UI thread, suggesting that the unnecessary UI rebuilds must be reduced.
Code after Micro-optiization

This code implements a debounce mechanism for the search input in the EarnScreen by delaying the execution of the filtering function until the user stops typing for 300 milliseconds. Each time the user types a character, any existing timer is canceled and restarted, ensuring that the filtering logic _applyFilterSort() only runs after the user pauses typing, reducing redundant calls on every keystroke. Additionally, the filter runs immediately when the user submits the search. This optimization reduces unnecessary UI rebuilds and CPU/GPU usage caused by frequent setState() calls, resulting in smoother performance and a better user experience while maintaining responsive search updates.
Profiling After Micro-optimization
The memory profiling after optimization shows a significant reduction in transient allocations compared to previous runs, indicating more efficient memory management during live search input. The persistent heap size remains stable around 141 MiB, while the total bytes allocated have decreased, demonstrating fewer short-lived objects generated during user interaction. This improvement reflects the effectiveness of the debounce mechanism, which reduces unnecessary widget rebuilds and filtering operations triggered on every keystroke. Consequently, the application exerts less pressure on the heap and garbage collector, leading to smoother performance and lower memory overhead during search usage.
The Core Animation profiling after optimization indicates a noticeable reduction in total layout and display duration, with layout time dropping to approximately 544 ms and display time to 145 ms. The average duration per layout and display event has also decreased, reflecting more efficient UI rendering cycles.
The GPU profiling after optimization shows a significant reduction in total GPU time, with Fragment processing dropping to 11.25 seconds and Vertex processing to 2.51 seconds. The latency between CPU and GPU has also improved, averaging 1.66 ms overall and showing lower latencies for the Runner process specifically, indicating these improvements allow a more efficient rendering.
The Time Profiler reveals that the app’s main thread spends significant time in rendering and UI update cycles, with major contributions from Flutter’s rasterizer and rendering pipeline. The total duration of the main thread has decreased compared to previous runs, indicating improved efficiency in frame construction and layout processing. Notably, the average duration for layout and display phases has reduced, reflecting fewer costly UI rebuilds thanks to the debounce optimization.
Code Before Micro-optimization
Initially, the paginated product list _page was updated directly inside _loadMore() using setState(), which triggered a rebuild of the entire Earn screen widget tree every time more products were loaded. Each call to setState() caused the whole product list and related UI components to re-render, resulting in repeated computations and unnecessary UI updates during scrolling and pagination.
This approach caused excessive widget rebuilds even when only a small portion of the UI (the paginated list) needed to update. This inefficiency increased CPU and GPU usage and caused potential jank or frame drops, especially when loading large numbers of products or interacting with long lists. The redundant state updates and rebuilds led to costly layout recalculations and rendering passes, reducing app responsiveness and user experience.
Profiling Before Micro-optimization
For the profiling we use the CPU Profiler, Core Animation Activity, Time Profiler, Allocations, and GPU.
The memory profiling shows persistent allocations around 134 MiB, indicating high memory usage during scrolling and pagination interactions. The total bytes allocated remain very high, with a significant number of transient allocations, reflecting many short-lived objects generated from frequent widget rebuilds. This suggests that the current state management approach triggers redundant state updates and excessive widget rebuilds during scroll-driven UI changes, causing considerable memory leaks and less efficient memory management. Consequently, heap pressure is elevated, potentially leading to dropped frames and less smooth performance under load.
The Core Animation profiling before applying the ValueNotifier optimization shows higher layout and rendering times. The total duration of layout events is about 3.25 ms with an average duration near 147.65 μs, but these layout recalculations are more frequent and less efficient compared to optimized runs. The commit phase dominates the activity with a higher total duration. These metrics reflect the impact of unnecessary widget rebuilds and state changes during scrolling and pagination.
The GPU profiling before the ValueNotifier optimization reveals higher total GPU time, with fragment processing lasting about 6.81 seconds and vertex processing around 2.00 seconds. The latency between CPU and GPU averages 1.29 ms, indicating less efficient rendering synchronization. The substantial fragment workload suggests many unnecessary redraws and less efficient frame rendering. Moreover, the relatively higher GPU times for both the app (Runner) and system (backboardd) indicate lower graphics performance and less smooth animations.
The Time Profiler before the ValueNotifier optimization demonstrates less efficient CPU usage, with longer main thread durations compared to optimized runs. The majority of CPU time is consumed by the Runner process and Core Foundation run loop, with longer layout and rendering phases.
Code after Micro-optiization
The optimization refactors the paginated product list management by replacing the direct use of setState() and a mutable list with a ValueNotifier<List>. This change allows updates to the visible product page to notify only the relevant UI components without rebuilding the entire widget tree, significantly reducing unnecessary widget rebuilds during pagination. As a result, the app experiences improved performance, smoother scrolling, and more efficient resource usage when loading additional products dynamically.
Profiling After Micro-optimization
After applying the optimization, the memory profiling shows a noticeable reduction in both transient allocations and total bytes allocated compared to previous runs. Persistent memory usage remains stable, indicating efficient long-term resource management. The decrease in transient objects, especially in smaller memory chunks like 16 and 32 bytes, suggests fewer temporary objects are created during UI updates. This improvement reflects more efficient widget rebuilds and reduced pressure on the garbage collector, leading to improved memory performance and smoother app operation during pagination and list interactions.
The Core Animation profiling after optimization reveals a slight reduction in total duration, particularly in the commit and prepare phases, indicating more efficient UI update cycles. The average duration per event remains stable, while the reduced total number of events suggests fewer layout recalculations and rendering passes.
The GPU profiling after optimization shows a reduction in total GPU activity, with Fragment processing time decreasing to 6.54 seconds and Vertex processing time to 1.88 seconds. The latency from CPU to GPU remains low, indicating efficient communication. These improvements reflect a lighter rendering workload, likely due to fewer redundant redraws and more efficient widget updates during scrolling and pagination, resulting in smoother graphical performance and reduced GPU strain.
The Time Profiler shows a notable decrease in CPU time spent on the main thread and Flutter's rasterizer, indicating improved efficiency in rendering and frame processing. The time dedicated to layout, drawing, and rendering tasks is reduced, which suggests fewer unnecessary widget rebuilds and optimized UI update cycles during scrolling and pagination. Overall, the profile confirms that using ValueNotifier to manage the paginated list has effectively decreased the CPU overhead and improved the app's responsiveness.
There is no battery excesive use. The maximun is 410uA which is under the 1000uA. Is an expected use.
There is a Jank Frame. The main page takes more than 60ms to load an no products are shown. For solving this issue, the main page has been modified to be the product listing view, which works correctly.
Average CPU usage is under 5%. However, when opening the map, there is an excesive peak, reaching 48% of usage. It is necessary to optimize the maps functionality by decreasing the times the back is called and the images are fetched, as its seems like products are consulted from the back everytime the map moves.
There are constant garbage collections when a new view is opened.
However, the selected area is when the map is opened. As it is seen, the native allocated memory increases, meaning there are many process on the back requesting for storage, which happens because functions like getAllUsers(), and getProductsByUserId() are used, which required more strage than other functionalities.
This could be optimized by avoiding the getAllUsers search and filtering users by distance before bringing them from the database.
Regarding threads, there are different threads with considerable use time, however there is not a significant stack of calls over the threads.
As the image does not show significant information about the thread flow, it is possible to check more detailed.
For instance, the main thread and the render thread have most of the request and the apps flow
The map calls a getAllUsers, which loads more data than necessary in the app.
This can be modified by filtering the users by distance before bringing the data from the database. By doing this, the native memory allocation will decrease, as well as the CPU usage.
The original login validation creates multiple temporary string objects during text processing, leading to unnecessary garbage collection.
By implementing object pooling with a pre-allocated StringBuilder, we eliminate temporary object creation and reduce GC pressure.
This optimization reduces memory allocation by ~60% during form validation by reusing the same StringBuilder instance and avoiding intermediate String objects.
The original profile fragment performs individual UI updates for each field, causing multiple layout passes and inefficient rendering.
By implementing string caching and batched updates, we minimize layout calculations and reuse formatted strings.
This reduces UI update time by ~40% through batched operations and eliminates redundant string formatting through caching.
The original implementation doesn't properly manage Toast instances and cached objects, leading to potential memory leaks. By implementing proper resource management with objects reuse and cleanups strategies.
The main issue of the application was the constant increase of the native allocations, which caused an excesive memory usage. After doing the profiling of the app after the micro optimizations:
It is visible that the average native memory was of 100.5MB, decreasing almost a 100% when comparing to the first profiling done. As well, it is evident that the memory usage is not constantly increasing anymore. There are some natural peaks when storing information or consulting the external database, however, it has a constant behaviour. Also, there are less Garbage Collections, which helps the GUI to lag less and work smoother, improving the user's experience.
Features Delivered
Views:
- Product list
- Log In
- Register
- Home page
Feature | Description | Sprint |
---|---|---|
Product Browsing View (ProductList) | Basic screen to display products with filters by type and category. | 2 |
Custom Search Bar | Text-based search bar with real-time results and product suggestions. | 2 |
Search Filtering + Category Dropdown | Enables users to refine results by type (Buy/Rent) and subject. | 2 |
Login with Firebase Authentication | Authenticates users using email/password. Includes error handling and form validation. | 3 |
“Remember Me” using SharedPreferences | Locally saves email after login if checkbox is selected. Auto-fills input next time. | 3 |
Register View with Image Picker | Allows users to register, select gender, input info, and upload a profile photo. | 3 |
Connectivity Feedback in Login/Register | Displays AlertDialog if no connection is detected before authentication. | 3 |
Connectivity Feedback in ProductList | Shows offline banner and avoids Firestore call if no internet. | 3 |
Validation Feedback | Form fields provide real-time validation with custom error messages. | 3 |
Homepage with “Recently Added” Products | Loads products from Firestore or Hive (offline). Displays 5 newest items. | 4 |
Recommended Products (LRU-based) | Matches top search terms to product titles using LRU cache and shows them. | 4 |
Firestore + Hive Local Caching | Stores products locally and retrieves them offline using offline_products box. |
4 |
Offline State Banner (Homepage) | Red banner appears if connectivity is lost and fallback content is shown. | 4 |
Search History with SQLite + Backup File | Saves each query in a local SQL table and as a .txt file. |
4 |
SearchBar Async Integration | Uses Future /await to avoid UI freezes when querying Firestore or SQLite. |
4 |
Connectivity Stream Handling | Uses StreamSubscription to dynamically update app state on connectivity changes. |
4 |
Features Delivered
Views:
- ProductDetail View (ProductDTable) – Focused on displaying detailed product info to users.
- NearbyProductsMap View – Displays products located near the user using map markers.
- Profile View – Shows user's data and product lists.
- Product Summary for Owner View – Oriented toward displaying a summary of products from the owner’s perspective, not the buyer's.
Feature | Description | Sprint |
---|---|---|
Product Detail View with Dynamic Action Buttons | Built the ProductDetail screen. Buttons shown (Buy, Rent, Bid) depend on the product type. Connected to Firestore to fetch product data and dynamically interact with other team components like the product search list. | 2 |
Shared Preferences for Time Tracking | Captures the timestamp when a user starts and ends a product search. Stores data in SharedPreferences and calculates search duration for analytics pipeline logging. | 2 |
Nearby Products Map with Google Maps Integration | Displays product markers based on geolocation. Connected to Google Maps API and loads product data from Firestore. | 3 |
Eventual Connectivity Strategy (Map View) | Detects internet status before and after loading. If disconnected, displays banners indicating offline mode or outdated content. | 3 |
Flutter Cache Manager for Product Images | Downloads and caches product images for markers locally using device storage. Leverages the local file system to persist image files for performance and offline support. | 3 |
Local Caching with Hive (Map View) | Saves fetched product data locally in Hive boxes to enable data persistence and offline support in the map screen. | 3 |
Multithreading with Futures (Map View) | Uses async/await and Futures to prevent UI blocking during data retrieval and map rendering. | 3 |
Multithreading with Futures (Repository Services) | Implements async/await logic in service functions to improve responsiveness when interacting with Firestore and APIs. | 3 |
Eventual Connectivity Strategy (Profile View) | Saves profile and product lists to Hive. Displays offline banner when disconnected. Ensures fallback rendering with possibly outdated data. | 3 |
Reject Rent and Bidding Offers (Profile View) | Enables product owners to decline incoming rent or bidding offers directly from the profile view. Supports seller-side control over their posted items. | 3 |
LRU Caching for Profile Product Lists | Implements Least Recently Used eviction for stored product lists in the Profile view, optimizing memory use and local data handling. | 4 |
Eventual Connectivity Strategy (Product Detail in Profile) | Persists product detail data in local Hive storage. If disconnected, allows viewing last known product state with a warning banner. | 4 |
Accept Rent and Bidding Offers (Profile View) | Adds functionality to accept incoming rent or bidding offers from the profile view, finalizing transactions. | 4 |
In-memory Icon Caching for Nearby Products | Stores BitmapDescriptors in a temporary Map<String, BitmapDescriptor> cache to avoid redundant icon generation for map markers. Improves performance when rendering nearby product icons near the user's location. |
4 |
Streaming for Connectivity State Updates | Implements a StreamSubscription to dynamically detect and respond to connectivity changes. Used to update UI and inform users of online/offline status in real time. |
4 |
Features Delivered
- PostProductScreen
- PostProductViewModel
- DatabaseHelper
- EarnScreen
- SellProductDetail
- SellProductDetailViewModel
Feature | Description | Sprint |
---|---|---|
Post Product Screen (PostProductScreen ) |
UI to create a new product: image selection (gallery or camera), form fields (title, description, category, price, base bid, transaction types, contact email), real-time validation and loading indicator. | 2 |
Image Compression & Upload (PostProductViewModel ) |
Decodes, resizes and compresses images using image + flutter_image_compress , then uploads to S3 via FirestoreService . |
2 |
Connectivity Check & Offline Fallback | Uses connectivity_plus to detect network; when offline, saves the product and its image path locally in SQLite (DatabaseHelper ). |
3 |
Local SQLite Persistence (DatabaseHelper ) |
Thread-safe helper for pending_products table: insert (dedup by attemptId ), query, delete, plus image-saving under app documents. |
3 |
Debounce & Single Submission | Prevents duplicate taps in PostProductScreen using a 2s Timer debounce and _isProcessing flag. |
3 |
Earn Screen (EarnScreen ) |
Product discovery view: fetches “Available” items from Firestore; category filter dropdown; text search with real-time filtering. | 3 |
SQLite Sparse Cache (EarnScreen ) |
Implements a simple “sparse” cache in SQLite (sparse_cache table) to record search terms for later analytics. |
3 |
Product Detail Screen (SellProductDetail ) |
Shows product images (carousel), title, price, description and seller info. Includes “Sell” button and contact actions (email, call, map). | 3 |
Detail ViewModel (SellProductDetailViewModel ) |
Async fetch of product + owner details from Firestore; exposes loading/error states to the UI. | 3 |
Infinite Scroll in Earn Screen | Pagination implementation with automatic loading of more products when reaching the list end. | 4 |
Share Listing from Detail Screen | Button to share the product link and details directly from the detail screen. | 4 |
Advanced Sort & Filter in Earn Screen | Combined category filters and search with sorting by price and date to improve user experience. | 4 |
Step Logging | Logs each post step (start_post , image_selected , post_success ) through FirestoreService.logPostStep and a final logProductPosting . |
4 |
Features Delivered
- Map: Find close products to your location -> Sprint 2
- Product listing: Show products with their price, image and description. Filtering can be done by type of action (buy, rent, earn) -> Sprint 3
- Create product: Post product name and description -> Sprint 3
- Create product: Post a product with its image, description, price, type and category. -> Sprint 4
- Optimize map feature: Reduce allocated memory and CPU usage -> Sprint 4 All views are protected to eventual connectivity events.
Features Delivered
- Auth: Login and Register of the APP -> Sprint 2
- Profile: Capability to see the logged profile and being able to log off. -> Sprint 3
- HomePage: Redesing since the other partner didnt finish it. -> Sprint 4
- Micro-optimized Profile: Reducing the UI update time. -> Sprint 4
Features Delivered
Business Question | Type | Rationale | Sprint |
---|---|---|---|
Which marketplace features (filters, entrepreneurship, messaging) are used the most and the least? | 3 | From this screen, we can track how often users interact with "Rent", "Buy Now", or "Place a Bid" options. | 2 |
What is the most popular price range for different academic materials? | 4 | Understanding popular price ranges allows distributors or sellers to price items competitively and design better promotions. | 3 |
How much time does it take for the material list to be available for users? Is it under 100ms on average? | 1 | Measures system performance and responsiveness to ensure a smooth user experience. | 4 |
Business questions to implement
Business Question | Type | Rationale | Sprint |
---|---|---|---|
Which marketplace features (filters, entrepreneurship, messaging) are used the most and the least? | 3 | Posting a product is one of the core features. Measuring its usage frequency helps determine whether it needs UX improvements or better visibility. | 4 |
Given the data recompiled from the marketplace, which materials/type of materials are being sold the most? | 4 | Posting a product includes selecting a category and type. Analyzing this data reveals trends in what users post, helping inform marketing strategies and partnerships. | 4 |
Business Question | Type | Rationale | Sprint |
---|---|---|---|
How does the app handle multiple users searching for the same material simultaneously? | 1 | Evaluates system scalability when users use search and filter features in the ProductList screen. | 2 |
How easy was it for you to find the product you were looking for? Did it take more than 5 seconds? | 2 | Measures efficiency of search/filtering mechanisms inside the ProductList screen to identify UX improvements. | 3 |
What is the ratio of views/transactions for each feature? | 3 | Helps detect features with high traffic but low conversions, signaling possible UX or trust issues. | 4 |
Business Question | Type | Rationale | Sprint |
---|---|---|---|
How does the system handle 100+ concurrent login attempts while maintaining sub-second response times? | 1 | Tests whether coroutine threading and Firebase Auth can sustain performance during traffic spikes without degrading local SharedPreferences caching efficiency. | 2 |
What percentage of users abandon the registration flow when encountering >2 form validation errors? | 2 | FMeasures UX friction caused by validation design, identifying if error messaging or validation sequencing drives user dropouts. | 3 |
Business questions to implement
Business Question | Type | Rationale | Sprint |
---|---|---|---|
Where do users spend the most time within the app, and how can we optimize these sections for better engagement? | 5 | With the analytics pipeline and the implementation of the session class, the time spent in each feature can be timed. | 2 |
Which listing attributes (images, descriptions, seller rating) impact purchase decisions the most? | 5 | When listing a product, clicks can be measured in each feature of the product, making possible to understand what attibute is more valuable for the buyer. | 3 |
Eventual Connectivity Strategy (ECn)
Feature/View | Strategy | Technologies | Antipattern Fixed |
---|---|---|---|
Login | Before attempting login, the app checks for internet using connectivity_plus. If offline, it blocks the request, shows a CircularProgressIndicator during processing, and then presents a clean AlertDialog explaining the issue. Technical exception traces are caught and hidden from the user. | connectivity_plus, try-catch, AlertDialog, CircularProgressIndicator |
MET (Message with Exception Trace) |
ProductList | The app checks connectivity before querying Firestore. If offline, it skips the network call and loads product data from local Hive storage (offline_products). A red banner ("You are offline. Showing stored products.") is displayed. | connectivity_plus, Hive, offline banner UI | NIM (Non-Informative Message), SPN (Stuck Progress Notification) |
Homepage (Recently Added) | The _loadProducts() method now stores Firestore data in Hive. On launch, the app checks for connectivity: if offline, it loads from cache using _loadCachedProducts() and sets _isOffline = true, triggering a user-visible warning. | Hive, connectivity_plus, conditional UI rendering | NNPPA (No Notification for Failed Action) |
Image Loading | Product images are cached automatically by cached_network_image, allowing them to be shown offline if previously viewed. This improves visual continuity even with limited connectivity. | cached_network_image | NIM (Visual delay due to uncached image) |
Local Storage Strategy
Feature/View | Strategy | Technologies | Stored Data |
---|---|---|---|
LoginPage – Remember Me | Stores the last email entered using SharedPreferences when the "Remember Me" checkbox is selected. Prefills email field on next login. | SharedPreferences(Key/Value store) | Email string (saved_email) |
Homepage – Product Caching | On successful Firestore fetch, product objects are stored in the Hivebox offline_products. On offline access, _loadCachedProducts()reads this local data. | Hive (NoSQL local DB) | Product list (as JSON maps) |
SearchBar – Search History | Saves each search term with a timestamp in a local SQLite database, enabling search suggestions and trend analysis. | SQLite via sqflite | Search terms with timestamps |
SearchBar – Backup File | As a backup, each search term is also appended to a local .txt file using Dart's FileSystem API, ensuring redundancy. | dart:io (plain text file) | List of search terms (one per line) |
Caching Strategy
Feature | Strategy | Technologies | Policy |
---|---|---|---|
Product Images | Images loaded via network are automatically stored in memory and on disk for future reuse. Memory cache is faster but volatile; disk cache persists between sessions. | cached_network_image | Memory + disk cache with LRU eviction |
Homepage – Product List | Products are cached in Hive after successful Firestore fetch. These are retrieved during offline access, enabling full app navigation without internet. | Hive | Manual overwrite per fetch |
Homepage – Recommended Products | Uses a custom LRUCache implementation (via LinkedHashMap) to store up to 5 most relevant products based on search history. | In-memory LRUCache | Auto-evicts oldest item (LRU) when full |
Multithreading / Concurrency Strategy
Feature / View | Strategy Type | Description | Benefit |
---|---|---|---|
SearchBar | Future + async/await | Handles I/O-bound operations like fetching products, saving search terms, and backups. | Keeps UI responsive during data-heavy tasks. |
LoginPage | Future with handler (.then()/ .catchError()) | Loads and stores user email asynchronously for the "Remember Me" feature. | Separates success/error handling; smooth login experience. |
HomePage | Stream (StreamSubscriptionfor connectivity) | Monitors network status and triggers product refresh or cache fallback. | Enables real-time reaction to connectivity changes. |
HomePage (LRU) | Future, Async recommendation filtering | Filters products using top search terms and stores results in memory. | Provides quick access to relevant items; avoids recomputation. |
_loadCachedProducts() | Future, Async local data loading | Loads product data from Hive cache when offline. | Enables offline navigation and improves startup performance. |
Eventual Connectivity Strategy (ECn)
Feature/View | Strategy | Technologies | Antipattern Fixed |
---|---|---|---|
NearbyProductsMap | Before rendering the map, the app checks connectivity. If offline, it displays a red banner notifying the user and avoids attempting to load remote product data. | connectivity_plus, Hive, conditional UI rendering | NNPPA (No Notification for Failed Action) |
ProductDetail (Profile View) | Stores product detail in Hive. If user loses connectivity, previously saved data is shown along with a banner explaining possible outdated content. | Hive, connectivity_plus, offline UI fallback | NIM (Non-Informative Message) |
Profile View | Full profile content (including posted/rented/bought products) is cached in Hive. If offline, the app shows cached data with a notification that it may be outdated. | Hive, connectivity_plus | NNPPA, NIM |
NearbyProductsMap | Streaming is used to monitor connectivity in real time. When status changes, the view is updated or offline warnings are triggered accordingly. | StreamSubscription, connectivity_plus | SPN (Stuck Progress Notification) |
Local Storage Strategy
Feature/View | Strategy | Technologies | Stored Data |
---|---|---|---|
Profile View | Stores full product history in Hive (posted, rented, bought). Enables offline access and fallback rendering. | Hive (NoSQL) | Product lists as JSON |
ProductDetail (Profile View) | Product data is stored in Hive to ensure accessibility even if internet connection is lost during navigation. | Hive | Product details |
NearbyProductsMap | Products fetched from Firestore are cached using Hive to support offline display. | Hive | Nearby product list |
LoginPage – Search Timing | Stores timestamp of user search initiation to later calculate total search time. | SharedPreferences | Timestamp (search_start_time) |
LoginPage – Remember Me | Stores email address locally to pre-fill login input on next session. | SharedPreferences | Email string (saved_email) |
Caching Strategy
Feature | Strategy | Technologies | Policy |
---|---|---|---|
NearbyProductsMap – Marker Icons | Custom icons are cached in-memory using a temporary map to avoid regenerating image descriptors repeatedly. | In-memory cache (Map) | Manual eviction on reload |
NearbyProductsMap – Product Images | Images are downloaded and cached locally using Flutter Cache Manager. | Flutter Cache Manager | Disk cache with expiration |
Profile View – Product Lists | Product data is stored in Hive after initial fetch. | Hive | Manual overwrite per fetch |
Profile View – LRU Cache | Stores recent product summaries in a custom LRU cache to limit memory footprint. | LinkedHashMap (manual LRU) | Auto-eviction of least used |
Product Images (Map and Profile) | Cached both in memory and on disk to ensure availability during offline use. | Flutter Cache Manager | Memory + Disk with expiration |
Multithreading / Concurrency Strategy
Feature / View | Strategy Type | Description | Benefit |
---|---|---|---|
NearbyProductsMap | Future + async/await | Loads product data and icons asynchronously to avoid blocking UI during map rendering. | Improves scroll and zoom performance. |
Repository Services | Future + async/await + .then/.catchError | All service-level calls to Firestore and APIs are non-blocking and handled safely. | Keeps business logic robust and responsive. |
LoginPage – Search Tracking | Async call to SharedPreferences for reading and writing search timing data. | Prevents blocking UI on login tracking operations. | |
Profile View | Future + async/await | Fetches and caches multiple product lists concurrently. | Reduces load time for profile screen. |
Connectivity Listener | StreamSubscription | Reacts to network changes in real time to trigger UI updates. | Seamless offline/online transition. |
Accept/Reject Offers (Profile Detail) | Async methods | All offer-handling logic (rent/bid) is processed asynchronously to ensure responsiveness. | Avoids UI freezing during transaction updates. |
Eventual Connectivity Strategy (ECn)
Feature/View | Strategy | Technologies | Antipattern Fixed |
---|---|---|---|
Post Product | Before posting a product, connectivity is checked using connectivity_plus . If offline, the product is saved locally for later upload. A snackbar informs the user. Automatic retry happens once online. |
connectivity_plus, Hive/SQLite, Snackbar | MET (Message with Exception Trace hidden) |
Earn List | When loading the product list, the app checks connectivity. If offline, cached products from Hive are loaded and a red banner notifies the user they are viewing offline data. Online data updates cache for future offline use. | connectivity_plus, Hive, Banner UI | NIM (Non-Informative Message), SPN (Stuck Progress Notification) |
Sell Product Detail | Product images load via CachedNetworkImage , which caches images for offline viewing. A placeholder shows while loading and an icon if the image fails to load. |
cached_network_image | NIM (Visual delay due to uncached image) |
Local Storage Strategy
Feature/View | Strategy | Technologies | Stored Data / Purpose |
---|---|---|---|
Earn Screen - Product Caching | On successful Firestore fetch, product data is saved locally using Hive. When offline, cached products are loaded from Hive to allow offline browsing. A red banner informs the user they are viewing offline data. | Hive (NoSQL local DB), connectivity_plus | Product list cached as JSON maps for offline access |
Sell Product Detail & Earn Screen - Image Caching | Product images are loaded using CachedNetworkImage , which caches images on disk. This allows displaying images even when offline, improving UX continuity. |
cached_network_image | Cached product images stored on device for offline viewing |
Post Product - Offline Save | When posting a product without internet connectivity, product details and image are saved locally (Hive/SQLite). Once connection is restored, uploads are retried automatically. | Hive/SQLite, connectivity_plus | Pending product data and images saved locally for deferred upload |
Earn Screen - Search History Cache | Search terms entered by the user are saved with timestamps in a local SQLite database. This enables quick search suggestions and trend analysis, enhancing user experience. | SQLite via sqflite | Search terms with timestamps stored locally for suggestion and analytics |
Caching Strategy
Feature | Strategy | Technologies | Policy |
---|---|---|---|
Product Images (Earn & Sell Detail) | Images are loaded with CachedNetworkImage , which caches images in memory and on disk for faster loading and offline viewing. |
cached_network_image | Memory + disk cache with automatic eviction (LRU) |
Earn Screen - Product List | Products are cached locally in Hive after successful Firestore fetch. On offline access, cached products are loaded to ensure continued browsing. | Hive, connectivity_plus | Manual overwrite of cache on each fetch |
Post Product - Offline Save | When posting without internet, product data and images are saved locally (Hive/SQLite). Upload retries happen when back online. | Hive/SQLite, connectivity_plus | Manual save and retry mechanism |
Search History (Earn Screen) | Search terms entered by users are cached in local SQLite database, allowing for quick search suggestions and trend analysis. | SQLite via sqflite | Persistent storage with timestamp tracking |
Multithreading / Concurrency Strategy
Feature / View | Strategy Type | Description | Benefit |
---|---|---|---|
Earn Screen | Future + async/await | Maneja la carga inicial y paginación de productos, lectura y escritura en Hive y llamadas a Firestore de forma asíncrona. | Mantiene la UI responsiva durante carga y actualizaciones. |
Earn Screen - Scroll | Listener + setState | Usa ScrollController para detectar cuándo cargar más productos (paginación infinita) y actualizar UI. | Permite carga incremental sin bloquear la UI. |
Earn Screen - Connectivity | StreamSubscription (connectivity_plus) | Escucha en tiempo real los cambios en la conexión a internet y actualiza la UI para mostrar o ocultar el banner offline, además de recargar datos cuando se recupera la conexión. | Permite reacción inmediata a cambios de conectividad, mejorando experiencia usuario. |
Post Product Screen | Future + async/await + Timer | Maneja la subida de productos, validaciones y debounce con temporizador para evitar envíos múltiples rápidos. | Evita múltiples posts simultáneos y mejora experiencia UX. |
Post Product Screen | Future con manejo de excepciones | Captura errores de conectividad y almacenamiento local para manejar reintentos offline. | Proporciona manejo robusto de errores para carga offline. |
Eventual Connectivity Strategy (ECn)
Feature/View | Strategy | Technologies | Antipattern Fixed | Sprint |
---|---|---|---|---|
Map | Map and location data are cached. If there is no Wi-Fi or location access, previously fetched nearby products and users are shown. Room is used to store product data, and an LRU cache saves the last known location. Toasts notify users of issues. |
try-catch, Room, LRU cache, Toasts | NNPPA (No Notification for Failed Action), Lost Content (Firebase unavailable), Map File Embedded Incorrectly |
3 |
Product List | Products are stored locally using Room . If there's no network connection, cached products are shown and the user is informed with a toast. |
Room, Toasts | LOS (Lack of Offline Support) | 3 |
Create Product | If there's no internet, the user is notified. The product creation request is stored in a local queue and posted automatically once the connection is restored. | Room, Toasts, Offline Queue | LOS (Lack of Offline Support), NNPPA (No Notification for Failed Action) |
4 |
Local Storage Strategy
Feature/View | Strategy | Technologies | Stored Data |
---|---|---|---|
Map / Product Views | Products and users are cached locally using Room to minimize Firestore queries and ensure offline access across map, listing, and creation features. | Room (Relational DB) | Product and user entities |
Product List | Product data is saved locally in Room after fetching from Firestore. On offline access, the app displays this cached data instead of making a network call. | Room (Relational DB) | Products |
Realm Logging | App logs and user interactions are saved locally using Realm to support analytics and later analysis (e.g., answering BigQuery questions). | Realm (Key/Value + Object DB) | Interaction logs, navigation events |
Product List Preferences | User preferences such as selected filters, categories, or sorting methods are stored using UserDefaults to personalize product listings. | UserDefaults (Key/Value store) | Last filters used, preferred categories, view history |
Caching Strategy
Feature | Strategy | Technologies | Policy |
---|---|---|---|
Product Images | Images are loaded through caché using a library that makes easier and faster the image loading | Glide | disk cache persists between sessions. |
Location | Location is cached using a datastructure. | LRU | disk cache persists between sessions. |
Multithreading / Concurrency Strategy
Feature / View | Strategy Type | Description | Benefit |
---|---|---|---|
Product List | Dispatcher | When loading products, a dispatcher is used to avoid freezing the UI while info is fetched from the databased. | Everytime products are loaded from the external database, they are copied in the local database. This a extensive process that might take time and freeze the UI if is not done in a corroutine. |
Map | Dispatcher/Corroutine insde a corroutine | For loading the users and products close to you on the map a corroutine calls another to avoid the UI freezing while showing the close products, updating the local DB and finding the products by user. | Smooth use of the map functionality |
Create Product | Dispatcher | When a product is created, the save action is done in the background to make smoother the user experience and avoiding freezes on the UI | The UI is available for showing process to the user. |
Map | Async network status | The app is able to check if network status has changed through asynchronous callbacks. | Updates the functionality of the app depending on the internet status that is updated concurrently. |
Eventual Connectivity Strategy (ECn)
Feature/View | Strategy | Technologies | Antipattern Fixed | Sprint |
---|---|---|---|---|
Login/Register |
Before executing auth.signInWithEmailAndPassword , check for internet availability. A function was created to check connectivity and integrated into the Login and Register processes. Exceptions are handled by showing user-friendly messages. Session persistence only occurs after a successful login. |
Connectivity Check, Error Handling | NNPPA (No Notification for Failed Action), Generic Toast Errors, No Retry Mechanism |
3 |
Local Storage Strategy
Feature/View | Strategy | Technologies | Antipattern Fixed | Sprint |
---|---|---|---|---|
Shared Preferences | Session persistence implemented using SharedPreferences with secure MODE_PRIVATE . Stores login state (is_logged_in ) to maintain authentication status between app sessions. Example code snippet: |
SharedPreferences, MODE_PRIVATE | Lost Session State (no persistence), Insecure Local Storage (fixed via private mode) |
3 |
Caching Strategy
Feature/View | Strategy | Technologies | Antipattern Fixed | Sprint |
---|---|---|---|---|
Profile Data Caching | Layered caching strategy with Room DB for local persistence + Firestore real-time updates. Implements auth-triggered cache invalidation and automatic sync on session renewal. Uses SharedPreferences for session state tracking. |
Room, Firebase Firestore, LiveData/Flow | Session-based stale data (fixed via logout purge), Network overfetching (cached profiles) |
3 |
Auth Sync | Dual-layer cache invalidation on logout: 1. Immediate SharedPreferences clearance2. Async Room DB purge 3. Firestore connection reset |
Firebase Auth, Room DB, Coroutines | Zombie sessions (fixed via chain purge), Cross-user data leakage |
3 |
Error Handling | Cache fallback mechanism: - Primary: LiveData from Room - Fallback: Firestore snapshot listeners - Emergency: Local SharedPreferences defaults |
LiveData, Firestore Snapshot Listeners | Cache corruption crashes (fixed via layered fallback) | 3 |
Multithreading / Concurrency Strategy
Feature/View | Strategy | Technologies | Antipattern Fixed | Sprint |
---|---|---|---|---|
User Registration | Non-blocking auth flow with Main dispatcher coroutine scope. Uses await() suspending functions for Firebase ops. Structured concurrency with try/catch error boundaries. UI responsiveness priority. |
Kotlin Coroutines, Firebase Auth, LiveData | UI Freeze during registration (coroutine solution), Unhandled async errors |
3 |
Data Serialization | Thread-confined HashMap creation in main thread with async Firestore write pattern. Coroutine context switching between Main ↔ IO via withContext . |
Dispatchers.IO, HashMap, Firestore | Background thread UI mutations (fixed via Main dispatcher), Race conditions |
3 |
Error Handling | Structured exception handling: 1. Auth exceptions caught in coroutine scope 2. Null checks with throw 3. Automatic cancellation propagation |
Coroutine Exception Handlers, try/catch | Silent failures (explicit throws), Unreleased resources on crash |
3 |
Eventual Connectivity Strategy (ECn)
Local Storage Strategy
Caching Strategy
Multithreading / Concurrency Strategy
https://github.com/Isarquis/M-viles-Group13/milestones
https://github.com/users/Isarquis/projects/3
Disclaimer: Pablo Mendez sent the video without audio and didn't answer again. We were forced to upload the video without his audio.