Skip to content

Conversation

@mkevins
Copy link
Contributor

@mkevins mkevins commented May 18, 2022

Fixes #16571

Description

This PR implements a preloading function in the main site creation view model, and invokes it when the site creation activity starts. It cancels the preloading before displaying the theme picker fragment so that the remaining images can load normally.

Preloading is done in the background via Glide, without layout specified (so only the original source image would be cached). This seemed a decent middle ground, imo, since it seeks to mitigate potential network performance issues (image resizing is done locally). If it is desirable to also prepopulate the resized results, an alternative to explore would be loading the entire fragment, but I have not attempted this.

To test:

Feature flag for convenience

Testing the behavior of this flow with and without the preloading can be tedious, since it requires clearing the cache every time. Also, there are multiple levels of cache, and it is difficult to get a fresh start without reinstalling the app for each test run. For convenience, I have added a temporary feature flag to toggle the preloading on and off. Also, each time the preloading (actually any feature flag is toggled 😄 ), the Glide cache is cleared (both memory and disk). It is also necessary to clear the app cache manually from the app info screen.

Precondition:

Start the app with the app inspection tab open, and the network inspector selected in Android Studio. It will be useful to monitor the traffic during the site creation flow.

Network inspector inspecting-mshots-requests

It can also be useful to perform these steps in an emulator, with a low data rate, e.g. GPRS & Poor.

Changing the network type and strength network-type-and-strength
Clearing the app cache
clear-app-cache.mp4

Preloading off

  1. Disable preloading in the app debug settings (and restart the app)
  2. Clear the app cache from the app info screen
  3. Start the site creation flow: Sites list -> "+" -> "Create WordPress.com site"
  4. Skip the intent screen
  5. Expect to land on the theme picker screen
  6. Highlight the traffic generated when this screen loads
  7. Expect that the layouts are fetched first, followed by the MShots thumbnails

Preloading on

  1. Enable preloading in the app debug settings (and restart the app)
  2. Clear the app cache from the app info screen
  3. Start the site creation flow: Sites list -> "+" -> "Create WordPress.com site"
  4. Highlight the traffic generated when this screen loads
  5. Expect that the layouts are fetched, followed by the MShots thumbnails
  6. Skip the intent screen
  7. Expect to land on the theme picker screen
  8. Expect that the layouts are fetched, but that the MShots thumbnails are not fetched

Preloading interrupted

  1. Enable preloading in the app debug settings (and restart the app)
  2. Clear the app cache from the app info screen
  3. Start the site creation flow: Sites list -> "+" -> "Create WordPress.com site"
  4. Note the time of the traffic generated when this screen loads
  5. Quickly skip the intent screen (before all the images are finished preloading)
  6. Expect to land on the theme picker screen
  7. Highlight the traffic generated while on both the intent screen and the theme picker screen
  8. Observe the requests in the highlighted traffic:
    • Expect that the layouts are requested first, followed by some (not all) of the MShots
    • Expect that the layouts are requested again, followed by the remaining MShots that were not precached by this mechanism

Regression Notes

  1. Potential unintended areas of impact
    Site creation flow

  2. What I did to test those areas of impact (or what existing automated tests I relied on)
    Manual testing

  3. What automated tests I added (or what prevented me from doing so)
    We don't currently have the needed integration test harness established to test this.

PR submission checklist:

  • I have completed the Regression Notes.
  • I have considered adding accessibility improvements for my changes.
  • I have considered if this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if necessary.

mkevins added 6 commits May 18, 2022 18:41
In order to make testing more convenient, this adds a temporary flag
that can be toggled in the debug settings of the app. It also adds a
hard-coded behavior to clear the Glide cache (memory and disk), for the
purpose of testing the flow with a fresh start each time.
For some reason, deleting the Glide cache was not enough, and disabling
the volley cache was still not enough to prevent a cache hit. I suspect
that there is an additional cache later on the network side of things.
Nevertheless, we may want to keep the volley cache disabled, to prevent
3 layers of duplicate cache.
The nested recycler views can only utilized a shared pool if they are
given the same instance of the pool. We can either remove the line, or
keep a reference to the instance at a higher level in the hierarchy, so
that the children recycler views can share a pool of view holders.
@mkevins mkevins added [Type] Enhancement Site Creation Part of a WIP Feature This label is used to disable milestone checks for PRs that are not against `develop` or `release`. labels May 18, 2022
@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented May 18, 2022

You can trigger optional UI/connected tests for these changes by visiting CircleCI here.

@mkevins mkevins requested review from antonis and ovitrif May 18, 2022 09:36
@peril-wordpress-mobile
Copy link

peril-wordpress-mobile bot commented May 18, 2022

You can test the changes on this Pull Request by downloading the APKs:

@mkevins
Copy link
Contributor Author

mkevins commented May 19, 2022

Some thoughts about other approaches

It occurs to me that with this approach, we are submitting the request for site designs (themes) and their categories twice: once at the start of the activity, in order to obtain the list of thumbnail URLs to prefetch, and once when the fragment loads. There is an opportunity for optimization here: we can save the result from the first call and avoid the second call if the first call is received in time (i.e. before the theme picker fragment is loaded).

Preload the whole fragment?

Another possibility to explore is to load the entire theme picker fragment invisibly at the start of the activity. Since we don't have the intent information at that time, the fragment would not in an identical ui state when it is finally displayed, but it might be possible, nevertheless, to populate both the Glide original source cache as well as many of the relevant resized caches (except the recommended row, since we can't know that ahead of time as it depends on the intent). Such an approach may have implications for the lifecycle of the underlying fragment (and view model).

One of the advantages of this approach is that we could be prepopulating both the original source image and the resized images generated by Glide to fit the given views. One limitation, however, is that we'd only be preloading items in the recycler view (and nested recycler views) that are "visible", and this would almost certainly be different after intent selection.

We could delay preloading until the intent is selected, but this leaves little time for preloading to be beneficial, since the picker is the very next screen shown. Later, with the site name screen re-enabled, this may put more weight towards such an approach.

@antonis
Copy link
Contributor

antonis commented May 19, 2022

Great work @mkevins 👍
Your approach looks good so far :)

There is an opportunity for optimization here: we can save the result from the first call and avoid the second call if the first call is received in time (i.e. before the theme picker fragment is loaded).

Maybe we can implement a caching mechanism on the network level similar to the one we have for the page layouts. I remember that we skipped this part in the original implementation because the users usually run this flow one. With the prefetching call though it makes sense to cache things.

@mkevins mkevins marked this pull request as ready for review May 20, 2022 06:59
@mkevins
Copy link
Contributor Author

mkevins commented May 20, 2022

Thanks for taking a look at this Antonis!

Maybe we can implement a caching mechanism on the network level similar to the one we have for the page layouts.

Good idea! I think this can be done in a followup PR. Wdyt?

@antonis
Copy link
Contributor

antonis commented May 20, 2022

Good idea! I think this can be done in a followup PR. Wdyt?

I agree since it would require a non-trivial amount of code and testing 👍

antonis added 2 commits May 20, 2022 15:04
Copy link
Contributor

@antonis antonis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @mkevins 👍
I've tested the build on an emulator (api level 32) and everything worked as described. The code changes look concise to me 🎉
Added a few suggestions and responses to your comments but nothing blocking for this PR 🙏

ps. I took the liberty to push minor changes to pash the CI test (lint, tests) 🙇

@mkevins mkevins merged commit 29c2398 into feature/site-design-revamp May 23, 2022
@mkevins mkevins deleted the feature/site-design-revamp--preload-mshots branch May 23, 2022 05:53
private val fetchHomePageLayoutsUseCase: FetchHomePageLayoutsUseCase
) : ViewModel() {
init {
// TODO: Remove the duplicate {,un}registration in the picker view model
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the cancellation (interruption) flow, we need to have this in both places. The only thing left to remove is this comment, which I forgot to remove before merging 🤦‍♂️ .

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed here 5351d73.

Part of PR: #16619

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ovi!

@ovitrif
Copy link
Contributor

ovitrif commented May 23, 2022

We could also remove the if check inside the when case

I agree, addressed here:
0d522e6

Part of PR: #16619

@mkevins
Copy link
Contributor Author

mkevins commented May 23, 2022

We could also remove the if check inside the when case

🤦‍♂️ why did I not see this 😅

Thanks for fixing it @ovitrif 👍 🙇‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Part of a WIP Feature This label is used to disable milestone checks for PRs that are not against `develop` or `release`. Site Creation [Type] Enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants