stripe-android icon indicating copy to clipboard operation
stripe-android copied to clipboard

Async ImageLoader with in-memory + disk cache (and compose usage showcase)

Open carlosmuvi-stripe opened this issue 2 years ago • 4 comments

Summary

  • Adds StripeImage composable, that accepts urls and loads them asynchronously.
  • Implements an in-memory LRU cache to cache loaded bitmaps.
  • Implements a disk LRU cache to cache loaded bitmaps.
  • Scopes Loader (and caches) to activity and exposes it to composables via staticCompositionLocal (not a requirement for its usage)

Motivation

  • Load images without depending on 3rd party libs.

Screenshots

image

carlosmuvi-stripe avatar Jul 20 '22 23:07 carlosmuvi-stripe

Diffuse output:

OLD: paymentsheet-example-release-master.apk (signature: none)
NEW: paymentsheet-example-release-pr.apk (signature: none)

          │            compressed            │            uncompressed            
          ├──────────┬──────────┬────────────┼───────────┬───────────┬────────────
 APK      │ old      │ new      │ diff       │ old       │ new       │ diff       
──────────┼──────────┼──────────┼────────────┼───────────┼───────────┼────────────
      dex │ 15.8 MiB │   16 MiB │ +198.9 KiB │  53.4 MiB │    54 MiB │ +627.7 KiB 
     arsc │  1.9 MiB │    2 MiB │  +60.6 KiB │   1.9 MiB │     2 MiB │  +60.6 KiB 
 manifest │  4.1 KiB │  4.1 KiB │      +55 B │  18.9 KiB │  19.4 KiB │     +452 B 
      res │    1 MiB │  1.1 MiB │  +38.2 KiB │   1.8 MiB │   1.8 MiB │  +42.8 KiB 
   native │  2.5 MiB │  2.5 MiB │        0 B │   5.9 MiB │   5.9 MiB │        0 B 
    asset │    3 MiB │    3 MiB │     +511 B │     3 MiB │     3 MiB │     +511 B 
    other │ 81.8 KiB │ 81.8 KiB │        0 B │ 155.7 KiB │ 155.7 KiB │        0 B 
──────────┼──────────┼──────────┼────────────┼───────────┼───────────┼────────────
    total │ 24.3 MiB │ 24.6 MiB │ +298.2 KiB │  66.1 MiB │  66.8 MiB │   +732 KiB 

         │           raw           │                unique                 
         ├────────┬────────┬───────┼────────┬────────┬─────────────────────
 DEX     │ old    │ new    │ diff  │ old    │ new    │ diff                
─────────┼────────┼────────┼───────┼────────┼────────┼─────────────────────
   files │      4 │      4 │     0 │        │        │                     
 strings │ 256346 │ 254546 │ -1800 │ 219199 │ 222562 │ +3363 (+3423 -60)   
   types │  45105 │  45943 │  +838 │  41474 │  42397 │  +923 (+938 -15)    
 classes │  38650 │  39554 │  +904 │  38650 │  39554 │  +904 (+919 -15)    
 methods │ 225198 │ 229313 │ +4115 │ 217408 │ 221580 │ +4172 (+4272 -100)  
  fields │ 164462 │ 164522 │   +60 │ 163493 │ 163551 │   +58 (+4576 -4518) 

 ARSC    │ old  │ new  │ diff           
─────────┼──────┼──────┼────────────────
 configs │  334 │  334 │    0           
 entries │ 6246 │ 6355 │ +109 (+109 -0)
APK
      compressed       │     uncompressed      │                                
──────────┬────────────┼──────────┬────────────┤                                
 size     │ diff       │ size     │ diff       │ path                           
──────────┼────────────┼──────────┼────────────┼────────────────────────────────
  2.9 MiB │ +444.4 KiB │  8.7 MiB │   +1.4 MiB │ ∆ classes3.dex                 
  2.9 MiB │ -393.1 KiB │    8 MiB │   -1.2 MiB │ ∆ classes4.dex                 
  3.4 MiB │ +147.5 KiB │    9 MiB │ +480.2 KiB │ ∆ classes2.dex                 
    2 MiB │  +60.6 KiB │    2 MiB │  +60.6 KiB │ ∆ resources.arsc               
 24.5 KiB │  +24.5 KiB │ 24.4 KiB │  +24.4 KiB │ + res/H5.png                   
  4.7 KiB │   +4.7 KiB │  4.6 KiB │   +4.6 KiB │ + res/4K.png                   
  2.6 KiB │   +2.6 KiB │  2.5 KiB │   +2.5 KiB │ + res/-j.png                   
  1.2 KiB │   +1.2 KiB │  2.2 KiB │   +2.2 KiB │ + res/q_.xml                   
    798 B │     +798 B │  1.9 KiB │   +1.9 KiB │ + res/JW1.xml                  
    691 B │     +691 B │  1.2 KiB │   +1.2 KiB │ + res/q3.xml                   
    676 B │     +676 B │  1.1 KiB │   +1.1 KiB │ + res/tV.xml                   
    662 B │     +662 B │  1.2 KiB │   +1.2 KiB │ + res/cO.xml                   
    613 B │     +613 B │    940 B │     +940 B │ + res/F9.xml                   
    589 B │     +589 B │    936 B │     +936 B │ + res/RS.xml                   
    550 B │     +550 B │    844 B │     +844 B │ + res/0k.xml                   
    529 B │     +529 B │    788 B │     +788 B │ + res/1O.xml                   
  9.7 KiB │     +518 B │  9.6 KiB │     +518 B │ ∆ assets/dexopt/baseline.prof  
    500 B │     +500 B │    804 B │     +804 B │ + res/ip.xml                   
    436 B │     -169 B │    692 B │     -412 B │ ∆ res/ZJ.xml                   
  4.1 KiB │      +55 B │ 19.4 KiB │     +452 B │ ∆ AndroidManifest.xml          
  6.9 MiB │       +8 B │ 28.4 MiB │        0 B │ ∆ classes.dex                  
    666 B │       -7 B │    534 B │       -7 B │ ∆ assets/dexopt/baseline.profm 
  1.3 KiB │       -3 B │  4.1 KiB │        0 B │ ∆ res/U9.xml                   
  1.1 KiB │       -2 B │  2.9 KiB │        0 B │ ∆ res/5d.xml                   
    798 B │       -2 B │  1.6 KiB │        0 B │ ∆ res/LG.xml                   
    324 B │       +2 B │    464 B │        0 B │ ∆ res/uP.xml                   
    760 B │       +1 B │  1.7 KiB │        0 B │ ∆ res/4L.xml                   
    493 B │       -1 B │    836 B │        0 B │ ∆ res/7A.xml                   
    997 B │       -1 B │  2.8 KiB │        0 B │ ∆ res/AE.xml                   
    707 B │       +1 B │  1.3 KiB │        0 B │ ∆ res/CF.xml                   
  1.1 KiB │       -1 B │  3.1 KiB │        0 B │ ∆ res/Cm.xml                   
    1 KiB │       -1 B │  3.1 KiB │        0 B │ ∆ res/Fs.xml                   
    600 B │       -1 B │  1.1 KiB │        0 B │ ∆ res/IZ.xml                   
    767 B │       +1 B │  1.5 KiB │        0 B │ ∆ res/M6.xml                   
    601 B │       +1 B │  1.1 KiB │        0 B │ ∆ res/MP1.xml                  
    726 B │       -1 B │  1.6 KiB │        0 B │ ∆ res/TP.xml                   
    529 B │       -1 B │    984 B │        0 B │ ∆ res/WT.xml                   
    736 B │       +1 B │  1.4 KiB │        0 B │ ∆ res/_Y.xml                   
  1.3 KiB │       -1 B │  3.9 KiB │        0 B │ ∆ res/_n.xml                   
  1.8 KiB │       +1 B │ 10.4 KiB │        0 B │ ∆ res/dn.xml                   
    829 B │       -1 B │  1.8 KiB │        0 B │ ∆ res/fx.xml                   
    620 B │       +1 B │  1.1 KiB │        0 B │ ∆ res/ib1.xml                  
    1 KiB │       +1 B │  2.6 KiB │        0 B │ ∆ res/j9.xml                   
    619 B │       +1 B │  1.2 KiB │        0 B │ ∆ res/jH.xml                   
    802 B │       +1 B │  1.7 KiB │        0 B │ ∆ res/wf.xml                   
──────────┼────────────┼──────────┼────────────┼────────────────────────────────
   18 MiB │ +298.2 KiB │ 56.1 MiB │   +732 KiB │ (total)
MANIFEST
@@ -264,2 +264,7 @@
             />
+        <data
+            android:host=link-accounts
+            android:path=/login
+            android:scheme=stripe-auth
+            />
       </intent-filter>
@@ -271,2 +276,8 @@
         />
+    <activity
+        android:exported=false
+        android:name=com.stripe.android.financialconnections.ui.FinancialConnectionsSheetNativeActivity
+        android:theme=@style/StripeDefaultTheme
+        android:windowSoftInputMode=0x16
+        />
     <provider
DEX
STRINGS:

   old    │ new    │ diff              
  ────────┼────────┼───────────────────
   219199 │ 222562 │ +3363 (+3423 -60) 
  + 
  
  
  
  
  ‡20B 0000R0¢R0¢R0¢R0¢¨
  + 
  
  
  
  
  ‡20B00R0¢R0¢¨
  + 
  
  
  
  
  
  
  
  
  ‡20BF00000	0
  0
  R0
  ¢R0¢
  R0¢R0¢
  R	0
  ¢	R0¢
  R0¢¨
  + ,
  
  
  
  
  
  
  
  
  
  
  
  
  ‡20B¦000000	0
  00
  000000000R
  00¢
  R0¢R0¢R0¢R0¢R0¢R00¢R0¢R0¢R0¢R0¢R0¢R	0¢	R0¢R0¢R
  0¢
  ¨
  + Z
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  020H020HUH		*H0
  
  *02
  
  
  002
  00H‡ø¢_H		*H0
  
  *0202
  
  
  002
  00H‡ø¢1H0	*H0
  *0*H	H¢KH0	*H0
  *0*H	2HH0H¢KH0	*H0
  *0*H	2HH0 H¢!‚
  ™20¨
  + _mapper
  + _mapper_inlined
  + _prop1
  + (Landroidx/lifecycle/LifecycleOwner;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;II)Lcom/airbnb/mvrx/MavericksViewModel;
  + (Lcom/airbnb/mvrx/MavericksViewModel;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
  + (Lcom/airbnb/mvrx/MavericksViewModel;Lkotlin/jvm/functions/Function1;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
  + (Lcom/airbnb/mvrx/MavericksViewModel;Lkotlin/reflect/KProperty1;Landroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
  + (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;Landroidx/compose/runtime/Composer;II)Lcom/airbnb/mvrx/MavericksViewModel;
  + (TS;)TA;
  + (TS;)TO;
  + -TS;+TO;>;
  + -TS;+TO;>;)V
  + C(collectAsState)
  + C(mavericksActivityViewModel)P(1)
  + C(mavericksViewModel)P(2,1)
  + Composable is not hosted in a ComponentActivity!
  + Lcom/airbnb/android/showkase/annotation/ShowkaseCodegenMetadata;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseColor;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseComposable;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseRoot;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseRootCodegen;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseRootModule;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseScreenshot;
  + Lcom/airbnb/android/showkase/annotation/ShowkaseTypography;
  + Lcom/airbnb/mvrx/compose/BuildConfig;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState__inlined_map_1_2_1;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState__inlined_map_1_2;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState__inlined_map_1;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState__inlined_map_2_2_1;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState__inlined_map_2_2;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState__inlined_map_2;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState_1;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState_3;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt_collectAsState_5;
  + Lcom/airbnb/mvrx/compose/MavericksComposeExtensionsKt;
  + Lcom/airbnb/mvrx/compose/R_anim;
  + Lcom/airbnb/mvrx/compose/R_animator;
  + Lcom/airbnb/mvrx/compose/R_attr;
  + Lcom/airbnb/mvrx/compose/R_bool;
  + Lcom/airbnb/mvrx/compose/R_color;
  + Lcom/airbnb/mvrx/compose/R_dimen;
  + Lcom/airbnb/mvrx/compose/R_drawable;
  + Lcom/airbnb/mvrx/compose/R_id;
  + Lcom/a
...✂
ARSC
ENTRIES:

   old  │ new  │ diff           
  ──────┼──────┼────────────────
   6246 │ 6355 │ +109 (+109 -0) 
  + drawable/stripe_check_account
  + drawable/stripe_check_base
  + drawable/stripe_check_routing
  + drawable/stripe_ic_brandicon_institution
  + drawable/stripe_ic_check
  + drawable/stripe_ic_check_nocircle
  + drawable/stripe_ic_edit
  + drawable/stripe_ic_external
  + drawable/stripe_ic_loading_spinner
  + drawable/stripe_ic_mail
  + drawable/stripe_ic_safe
  + drawable/stripe_ic_shield
  + drawable/stripe_logo
  + plurals/stripe_account_picker_confirm
  + plurals/stripe_attachlinkedpaymentaccount_desc
  + plurals/stripe_attachlinkedpaymentaccount_desc_no_business
  + plurals/stripe_attachlinkedpaymentaccount_title
  + string/consent_pane_manual_entry
  + string/consent_pane_tc
  + string/data_accessible_callout
  + string/data_accessible_callout_connected_accounts
  + string/data_accessible_callout_no_business
  + string/data_accessible_callout_through_stripe
  + string/data_accessible_callout_through_stripe_no_business
  + string/data_accessible_type_accountdetails
  + string/data_accessible_type_balances
  + string/data_accessible_type_ownership
  + string/data_accessible_type_transactions
  + string/stripe_account_picker_dropdown_hint
  + string/stripe_account_picker_error_no_payment_method_desc
  + string/stripe_account_picker_error_no_payment_method_title
  + string/stripe_account_picker_loading_desc
  + string/stripe_account_picker_loading_title
  + string/stripe_account_picker_multiselect_account
  + string/stripe_account_picker_select_account
  + string/stripe_consent_pane_agree
  + string/stripe_consent_pane_body1
  + string/stripe_consent_pane_body1_connected_account
  + string/stripe_consent_pane_body1_no_businessname
  + string/stripe_consent_pane_body2
  + string/stripe_consent_pane_body3
  + string/stripe_consent_pane_title
  + string/stripe_consent_pane_title_connected_account
  + string/stripe_consent_pane_title_no_businessname
  + string/stripe_consent_requested_data_accountdetails_desc
  + string/stripe_consent_requested_data_accountdetails_title
  + string/stripe_consent_requested_data_balances_desc
  + string/stripe_consent_requested_data_balances_title
  + string/stripe_consent_requested_data_learnmore
  + string/stripe_consent_requested_data_ownership_desc
  + string/stripe_consent_requested_data_ownership_title
  + string/stripe_consent_requested_data_title
  + string/stripe_consent_requested_data_title_no_businessname
  + string/stripe_consent_requested_data_transactions_desc
  + string/stripe_consent_requested_data_transactions_title
  + string/stripe_error_cta_select_another_bank
  + string/stripe_error_generic_desc
  + string/stripe_error_generic_title
  + string/stripe_error_planned_downtime_desc
  + string/stripe_error_planned_downtime_title
  + string/stripe_error_unplanned_downtime_desc
  + string/stripe_error_unplanned_downtime_title
  + string/stripe_institutionpicker_footer_item_manualentry
  + string/stripe_institutionpicker_footer_item_spelling
  + string/stripe_institutionpicker_footer_item_support
  + string/stripe_institutionpicker_footer_title
  + string/stripe_institutionpicker_pane_error_desc
  + string/stripe_institutionpicker_pane_error_desc_manual_entry
  + string/stripe_institutionpicker_pane_error_title
  + string/stripe_institutionpicker_pane_select_bank
  + string/stripe_manualentry_account
  + string/stripe_manualentry_account_type_disclaimer
  + string/stripe_manualentry_accountconfirm
  + string/stripe_manualentry_cta
  + string/stripe_manualentry_microdeposits_desc
  + string/stripe_manualentry_routing
  + string/stripe_manualentry_title
  + string/stripe_manualentrysuccess_desc
  + string/stripe_manualentrysuccess_desc_descriptorcode
  + string/stripe_manualentrysuccess_desc_noaccount
  + string/stripe_manualentrysuccess_desc_noaccount_descriptorcode
  + string/stripe_manualentrysuccess_table_title
  + string/stripe_manualentrysuccess_title
  + string/stripe_ok
  + string/stripe_partner_finicity
  + string/stripe_partner_mx
  + string/stripe_partner_testmode
  + string/stripe_partner_truelayer
  + string/stripe_partner_wellsfargo
  + string/stripe_picker_error_desc
  + string/stripe_picker_error_title
  + string/stripe_picker_loading_desc
  + string/stripe_picker_loading_title
  + string/stripe_picker_search_no_results
  + string/stripe_prepane_continue
  + string/stripe_prepane_desc
  + string/stripe_prepane_partner_callout
  + string/stripe_prepane
...✂

github-actions[bot] avatar Jul 21 '22 00:07 github-actions[bot]

Does this work for svg files as well?

jameswoo-stripe avatar Sep 19 '22 22:09 jameswoo-stripe

Does this work for svg files as well? would be great to be able to load Uri

Currently it does not support these. The idea here is to have the basic, and keep iterating over it as teams need it. @jameswoo-stripe @ccen-stripe

carlosmuvi-stripe avatar Sep 20 '22 18:09 carlosmuvi-stripe

@ccen-stripe @jameswoo-stripe @tillh-stripe Alternatively we can rely on coil-base (not the entire coil library) to run image requests. It'd add ~150kb to the binary, but we'd support all usecases, cache types, etc - https://github.com/stripe/stripe-android/pull/5584

carlosmuvi-stripe avatar Sep 20 '22 23:09 carlosmuvi-stripe