Splash screen not shown immediately (as in docs demo)

Hey all,

In android standalone app, the splash screen does not shown immediately after you click the app icon launcher.

Take a look at this gif-demo from the docs: gif-demo-link

My app should behave like the one on the far right (where the splashscreen is shown immediately, as in large apps like facebook, reddit etc). However my splash screen behaves like the one on the far left (first a white blank screen is shown, and then the splash screen appears).

Strange thing is, that sometimes before the splash screen, and after the initial white blank screen, a blue spinner is appearing (I have not registered this spinner anywhere in my app, maybe some fetching from expo servers is happening?)

My app.json (notice that I bundle all assets to be available instantly on app launch):

{
  "expo": {
    "sdkVersion": "30.0.0",
    "name": "MyApp",
    "icon": "./assets/icons/logo-512.png",
    "version": "0.0.2",
    "slug": "my-app-slug",
    "ios": {
      "bundleIdentifier": "com.me.myapp"
    },
    "android": {
      "package": "com.me.myapp"
    },
    "splash": {
      "resizeMode": "cover",
      "image": "./assets/images/splash.png"
    },
    "primaryColor": "#0077ff",
    "assetBundlePatterns": [
      "assets/images/*",
      "assets/icons/*",
      "assets/fonts/*"
    ]
  }
}

Any help is appreciated!

Hey @tasoskakour,

Can you share the relevant code where you are using the AppLoading API?

Cheers,

Adam

1 Like

Of course.

The scenario that I want to achieve is this:
(Keep in mind that this scenario is achived perfectly in development mode with expo, however everything goes wrong with the standalone app)

  1. User clickes on app launcher → the splash screen immediately shows (it’s just a 300kb png image)
  2. The App.js loads the fonts and icons that the application will need (the splash screen is still showing with autoHideSplash = false)
  3. As soon as the assets are loaded, I unmount the AppLoading and mount my application where the top navigation component is just a react-navigation switch with: “AuthLoading”, “AuthApp”, “PublicApp”
  4. Inside AuthLoading I want to show an image which is an exact replica of my splash image but with a loading text on it (the text embedded on image-png), so I listen for the onLoadEnd event to hide the splash and show the image. Despite using this method, I still see a white screen flickering (for 100ms) between splash screen and the AuthLoading component.
  5. Also, inside AuthLoading I call my server to check if the user is logged in (and has valid local credentials) and then I make the decision to route him to either the “AuthApp” or “PublicApp”

All the assets I have them in assetBundlePatterns in app.json (fonts and images)

So here’s the code:

App.js (AppIndex is the name of the top switch navigator)

export default class App extends React.Component {
    state = { isReady: false }

    cacheResources = () => {
        return Expo.Font.loadAsync({
            Roboto: require("./assets/fonts/Roboto.ttf"),
            Roboto_medium: require("./assets/fonts/Roboto_medium.ttf"),
            Ionicons: require("./assets/fonts/Ionicons.ttf"),
            Courgette: require('./assets/fonts/Courgette-Regular.ttf'),
        })
    }

    render() {
        if (!this.state.isReady) {
            return <Expo.AppLoading
                startAsync={this.cacheResources}
                onFinish={() => this.setState({ isReady: true })}
                onError={console.warn}
                autoHideSplash={false}
            />
        }
        return (
            <Provider store={store}>
                <PersistGate loading={null} persistor={persistor}>
                    <Root>
                        <StyleProvider style={getTheme(commonColor)}>
                            <AppIndex ref={navigatorRef => {
                                NavigationService.setTopLevelNavigator(navigatorRef);
                            }} />
                        </StyleProvider>
                    </Root>
                </PersistGate>
            </Provider>
        )
    }
}

AuthLoading.js (props {load,loading and loggedIn} are loaded with redux connect and refer to the authentication state of the user}

@connect(mapStateToProps, mapDispatchToProps)
export default class AuthLoadingScreen extends React.Component {
    state = { imageLoaded: false, navigationReady: false }

    componentDidMount = () => {
        this.props.load();
    }

    // Hackish solution to not let this component ever re-render, 
    // because if it is re-rendered before the image loadEnd event 
    // the loadEnd event is never called!
    shouldComponentUpdate = (nextProps) => {
        if (this.props.loading && !nextProps.loading) {
            if (this.state.imageLoaded) {
                this.applyNavigation(nextProps.loggedIn);
            } else {
                this.setState({ navigationReady: true })
            }
        }
        return false;
    }

    applyNavigation = loggedIn => {
        if (loggedIn) {
            this.props.navigation.navigate('AuthApp');
        } else {
            this.props.navigation.navigate('Start');
        }
    }

    _onLoadEnd = () => {
        Expo.SplashScreen.hide();
        this.setState({ imageLoaded: true })
        if (this.state.navigationReady) {
            this.applyNavigation(this.props.loggedIn)
        }
    }

    // Continuation of SplashScreen without flickering here (just like docs)
    // however flickering happens!
    render() {
        return (
           <View style={{ flex: 1 }}>
            <Image
                source={require('../../assets/images/splash_with_loading.png')}
                resizeMode='cover'
                style={{
                    flex: 1,
                    width: undefined,
                    height: undefined,
                    justifyContent: 'center',
                }}
                fadeDuration={0}
                onLoadEnd={this._onLoadEnd}
                onError={console.warn}
            />
        </View>
        );
    }
}

Anyone? :worried:

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.