5 Useful Tips for Kotlin Users

5 Useful Tips for Kotlin Users

In 2017 Google announced first-class support for Kotlin on Android at Google I/O, and shortly after I started looking into using Kotlin for our Android projects here at Shockoe. It took a few years before we officially started using Kotlin as our preferred language for Android development, but I now believe that using Kotlin instead of Java can make writing Android code easier, faster, and less prone to errors. I am going to list some of my favorite features of Kotlin that have improved my workflow.

1. Using val and var effectively in Kotlin, variables are declared with either the val or var keywords. Vals cannot be reassigned (like variables declared as final in Java) while vars can be reassigned after creation. If you need to reassign the value of a variable, you will have to declare it as a var. If you do not need to reassign the variable, you can declare it as a val. Kotlin can use static checks to perform common tasks automatically. Let’s take the example where the type of a variable can vary at runtime, and you want to perform different tasks based on the object’s type. If you use a var it might look like this. The var has to be cast to a String before you can perform any String functions on it.

When using a val, Kotlin can automatically cast the variable to a string inside the if statement

One goal the creators of Kotlin have is to eliminate NullPointer exceptions (NPEs) from our code. Kotlin’s type system has references that can hold null (nullable references) and references that can not (non-null references). Kotlin offers a few different tools for dealing with nullable references. If the reference is a val, it can be autocast to be non-null using an if statement, similar to the example in the last section. There is also the Safe Call option, written as ?., which will return the result of the expression if the reference is non-null or will return null if any reference in the chain is null. The next option is the Elvis Operator, written as ?:, which will return the result of the left side of the expression if it is not null, otherwise it returns a non-null reference that you specify. A good example of where to use this is in a RecyclerView Adapter that uses a nullable reference to store its data:

The last option is the !! operator. This is also the least safe option, because it is a non-null assertion operator. This operator can be dangerous because it will actually throw a NPE if it is called on a null value. This option should only be used when necessary because of the risks involved.

3. One of my favorite features of Kotlin is extension functions. These let you easily add new functionality to a class without having to inherit from it. This can be especially useful for Android development where it is difficult or cumbersome to inherit from classes like Context. Here is an example extension function that can be used to convert values from density-independent pixels to pixels.

I found that is is much easier to write extension functions for simple tasks like this, instead of having one big file with static functions. This function can also be used on any instance of Context or any of its descendants.

4. Functions in Kotlin are first class. They can be stored in variables and passed to other functions as parameters. I have found that storing function in variables is a good alternative to writing a Java interface that only has one method in it, such as a click listener:

5. Kotlin is interoperable with Java. Kotlin bytecode is indistinguishable from Java bytecode, and therefore the two can run alongside each other. If you have an existing project written in Java, you don’t need to rewrite all your existing classes to experience all the benefits of Kotlin. In one project, I had many classes where their main functionality was to hold data. I started by converting these classes to Kotlin Data Classes. With data classes, the compiler automatically creates some common functions: equals(), hashCode(), toString(), copy().

I think that Kotlin has some great features that can make developing faster and easier. JetBrains and Google have created some great tools for starting a project with Kotlin or adding Kotlin support to an existing Java project. Android Studio has an option to convert an existing Java file to Kotlin, and in my experience, it has worked pretty well. Because of Kotlin’s recent growth in the development community and the support provided by JetBrains and Google, I believe this is a perfect time to start using Kotlin if you have been at all curious about it.

Kyle Engler

Kyle Engler

Self-proclaimed Google Fanboy, Kyle is a Titanium and native Android developer who has been creating mobile applications for over 5 years. He is always on the lookout for new trends in the mobile space. Kyle is equally at home implementing a front-end UI as well as designing an application’s data architecture.

How to Combine Bottom Tabs, Top Tabs and a Hamburger Menu in a React Native Application

How to Combine Bottom Tabs, Top Tabs and a Hamburger Menu in a React Native Application

Mixing different navigation components can be tricky to implement as well as suggested against.  But there may be scenarios where you need to mix a few different components to encapsulate the experience you are looking to convey.   This guide will walk you through creating a simple application that contains bottom tab navigation, top tabs, and a hamburger menu to give you the basics of mixing navigation components.

First let’s initialize the project:

react-native init navigationExample

cd navigationExample

Once initialized we will need to install some packages. The first package we will install is react-navigation.  This will give you the hamburger menu and the bottom tabs and as the name might suggest allow you to navigate between different screens.  Run the following commands:

npm install –save react-navigation

npm install –save react-navigation-gesture-handler

react-native link

Android requires one extra step. Make sure your MainActivity.java looks like this:

package com.navigationexample;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "navigationExample";
    }

  @Override
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName()) {
      @Override
      protected ReactRootView createRootView() {
       return new RNGestureHandlerEnabledRootView(MainActivity.this);
      }
    };
  }
}

 

Now that we have that we will install Native Base.  Native Base is a library that allows use to different ui components and allows for simple styling.  Running the following commands with install Native Base:

npm install native-base –save

react-native link native-base

We will also install an icon package for access to some icons for the hamburger menu and bottom tabs.

npm install react-native-vector-icons

react-native link react-native-vector-icons

Awesome, now that we have the packages we need lets get started on the actual code.  First let’s create a `src` folder to hold our screen files. Then let’s create a couple basic screens.

src/DefaultScreen.js

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import Icon from 'react-native-vector-icons/SimpleLineIcons';

const instructions = Platform.select({
 ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
 android:
   'Double tap R on your keyboard to reload,\n' +
   'Shake or press menu button for dev menu',
});

export default class DefaultScreen extends Component {
 render() {
   return (
     <View style={styles.container}>
       <Text style={styles.welcome}>Welcome to React Native!</Text>
       <Text style={styles.instructions}>To get started, edit App.js</Text>
       <Text style={styles.instructions}>{instructions}</Text>
     </View>
   );
 }
}

const styles = StyleSheet.create({
 container: {
   flex: 1,
   justifyContent: 'center',
   alignItems: 'center',
   backgroundColor: '#F5FCFF',
 },
 welcome: {
   fontSize: 20,
   textAlign: 'center',
   margin: 10,
 },
 instructions: {
   textAlign: 'center',
   color: '#333333',
   marginBottom: 5,
 },
});

 

This file is the basic screen that react sets up for you when you start a project.

src/BlueScreen.js

import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
import Icon from 'react-native-vector-icons/SimpleLineIcons';


export default class BlueScreen extends Component {
    render() {
 	 return (
        <View style={styles.container}>
     	 <Text style={styles.title}>Blue Screen</Text>
        </View>
 	 );
    }
 }
  const styles = StyleSheet.create({
    container: {
 	 flex: 1,
 	 justifyContent: 'center',
 	 alignItems: 'center',
 	 backgroundColor: 'blue',
    },
    title: {
 	 fontSize: 20,
 	 textAlign: 'center',
 	 margin: 10,
    }
 });

Now that we have two screens we can add them to a Drawer Navigator.

src/HamburgerNavigation.js

import {
 createAppContainer,
 createDrawerNavigator,
} from 'react-navigation';
import BlueScreen from './BlueScreen';
import DefaultScreen from './DefaultScreen';

const HamburgerNavigation = createDrawerNavigator(
    {
        BlueScreen: BlueScreen,
        DefaultScreen: {
            screen: DefaultScreen,
        }
    },
    {
        initialRouteName: ‘DefaultScreen’,
        
        
    }
 );


export default createAppContainer(HamburgerNavigation);

You will then need to make a couple changes to you App.js to display the new screens.

App.js

import React, {Component} from 'react';
import HamburgerNav from './src/HamburgerNav'


export default class App extends Component {
 render() {
   return (
     <HamburgerNav/>
   );
 }
}

So now if you build your application with `react-native run-ios` or `react-native run-android` you should see the same default screen as you would if you started a react project from scratch.  The difference is if you swipe from left to right, you will see the drawer menu open. You can then open the BlueScreen. For now the drawer menu is only accessible from the swipe gesture we will allow the user to access it from the nav bar later.  The drawer navigator handles all the navigation to either screen which makes it easy to implement. Yet this isn’t the final implementation of the menu so more to come here. Now let’s get the bottom tabs in place.

src/BottomTabs.js

import React from 'react';
import { createStackNavigator, createBottomTabNavigator, createAppContainer } from "react-navigation";
import Icon from 'react-native-vector-icons/SimpleLineIcons';
import GreenScreen from "./GreenScreen";
import RedScreen from "./RedScreen";



const GreenTab = createStackNavigator({
    Green: GreenScreen
});

const RedTab = createStackNavigator({
    Red: RedScreen
});

const Tabs = createBottomTabNavigator({
    Green: GreenTab,
    Red: RedTab
}, {
    defaultNavigationOptions: ({ navigation }) => ({
        tabBarIcon: () => {
            const { routeName } = navigation.state;
            let tabName;
            tabName = routeName === 'Green' ? 'home' : 'grid';

            return <Icon name={tabName} size={20} />
        }
    })
});

export default createAppContainer(Tabs);

This file holds the logic for the bottom tab navigation.  Each tab has its own stack navigator that way if you wanted to add more screens on to one tab you could by simply adding them to the correct stack.  To set the icons for the specific tabs we use the tabBarIcon property within defaultNavigationOptions and set the icon based on the title of the tab.  You can do some more customizing of the tabs (active color, inactive color, padding, font etc.) with the tabBarOptions property. For now we are just sticking with the default tab styling.  For the sake of not showing too much of the same code GreenScreen and RedScreen are the same as the BlueScreen from earlier except for one minor difference.

import HamburgerIcon from './HamburgerIcon';

export default class GreenScreen extends Component {
    static navigationOptions = () => {
        return {
            headerLeft: <HamburgerIcon/>
        };
    };

In this snippet I created a hamburger icon to display on nav to allow access to drawer menu without the swipe gesture.  The hamburger icon was purely this custom component I created.

src/HamburgerIcon.js

import React, {Component} from 'react';
import { withNavigation } from 'react-navigation';
import { TouchableOpacity } from "react-native-gesture-handler";
import Icon from 'react-native-vector-icons/SimpleLineIcons';


class HamburgerIcon extends Component{
    render() {
 	 return (
        <TouchableOpacity
        style={{
            width: 44,
            height: 44,
            marginLeft: 20
        }}
        onPress={()=>{
            this.props.navigation.openDrawer();
        }}>
            <Icon name='menu' size={20} color='black'/>
        </TouchableOpacity>
 	 )
    };
}

export default withNavigation(HamburgerIcon);

 

We are almost there! We now have bottom tabs with a hamburger menu.  Last up is the top tabs using Native Base. For these we will just edit the GreenScreen render function to include the tabs.  

src/GreenScreen.js

import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';
import HamburgerIcon from './HamburgerIcon';
import { Container, Tab, Tabs, StyleProvider } from 'native-base';
import Tab3 from './Tab3.js';
import Tab2 from './Tab2.js';


export default class GreenScreen extends Component {
    static navigationOptions = () => {
        return {
            headerLeft: <HamburgerIcon/>
        };
    };
    render() {
        return (
            <Container>
                <Tabs>
                    <Tab
                    heading='Green Tab'>
                        <View style={styles.container}>
                            <Text style={styles.title}>Green Screen</Text>
                        </View>
                    </Tab>
                    <Tab heading='Tab 2'>
                        <Tab2 />
                    </Tab>
                    <Tab heading='Tab 3'>
                        <Tab3 />
                    </Tab>
                </Tabs>
            </Container>
        );
    }
 }
  const styles = StyleSheet.create({
    container: {
 	 flex: 1,
 	 justifyContent: 'center',
 	 alignItems: 'center',
 	 backgroundColor: 'green',
    },
    title: {
 	 fontSize: 20,
 	 textAlign: 'center',
 	 margin: 10,
    }
 });

 

First we imported the correct component we needed from Native Base and then updated the render function to include the tabs.  Within each tab we have added a couple components. For simplicity the Tab2 and Tab3 files are simply a component with a text within a view but you can make these looks however you want. If you wanted to you could create stack navigators for each of these tabs as well to allow you to open screens and still show the top tabs other wise you can use the stack navigator in which the GreenScreen already resides.  As mentioned earlier Native Base allows for easy customization of their components but for now we are sticking with the default. Check out the links at the bottom of the screen if you are interested in customizing Native Base components.

Now we are almost there!  A couple of things we need to clean up.  Number one we probably don’t want the tabs option actually showing in the drawer menu.  Number two need a back button for the screens with in the drawer menu. So for hiding the tabs from the drawer menu we will customize the content showing in the drawer menu using contentComponent property.  This allows us to customize exactly what shows in the drawer. We will just add two text components to access the two screens. You can do alot of cool thing with the ui of the drawer menu but this guide is focusing on the navigation structure. So let’s create a simple back button component to add to the BlueScreen and DefaultScreen.

src/BackButton.js

import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import { withNavigation } from 'react-navigation';
import { TouchableOpacity } from 'react-native-gesture-handler';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
class BackButton extends Component {
 render() {
   return (
     <TouchableOpacity
       style={styles.backButton}
       onPress={() => {
         this.props.navigation.pop();
       }}
     >
       <Icon
         name= 'chevron-left'
         size={20}
       />
     </TouchableOpacity>
   );
 }
}
const styles = StyleSheet.create({
 backButton: {
   height: 44,
   width: 44,
   justifyContent: 'center',
   alignItems: 'center',
 },
});
export default withNavigation(BackButton);

This back button component is just an icon within a TouchableOpacity and onPress just pop the screen the user is on from the stack.  Then within the BlueScreen and DefaultScreen import the back button and add this snippet.

static navigationOptions = () => {
        return {
            headerLeft: <BackButton/>
        };
 };

Last but not least we need to update the HamburgerNav.

src/HamburgerNav

import React from 'react';
import {
 createAppContainer,
 createDrawerNavigator,
 createStackNavigator,
} from 'react-navigation';
import { ScrollView } from 'react-native-gesture-handler';
import { SafeAreaView } from 'react-navigation';
import { Text } from 'react-native';
import BlueScreen from './BlueScreen';
import DefaultScreen from './DefaultScreen';
import BottomTabs from './BottomTabs';


const HamburgerNavigation = createDrawerNavigator(
    {
        Tabs: BottomTabs,
    },
    {
        initialRouteName: 'Tabs',
        contentComponent: props => {
            return (
                <ScrollView>
                    <SafeAreaView
                    forceInset={{ top: 'always', horizontal: 'never' }}
                >
                    <Text
                        onPress={() => {
                        props.navigation.navigate('BlueScreen');
                        props.navigation.closeDrawer();
                        }}
                    >
                        BlueScreen
                    </Text>
                    <Text
                        onPress={() => {
                        props.navigation.navigate('DefaultScreen');
                        props.navigation.closeDrawer();
                        }}
                    >
                        DefaultScreen
                    </Text>
                    </SafeAreaView>
                </ScrollView>
            )
        }
    }
 );

 const Stack = createStackNavigator(
 	 {
        Drawer: {
            screen: HamburgerNavigation,
            navigationOptions: {
                header: null,
            },
     	 },
        BlueScreen: BlueScreen,
        DefaultScreen: {
            screen: DefaultScreen,
        }
 	 }
 );


export default createAppContainer(Stack);

Here you can see the BlueScreen and Default screen now aren’t inside of the DrawerNavigator.  We add these two screens to StackNavigator that also contains the DrawerNavigator. This way these screens are opened on top of the drawer navigator. This is all made possible by the contentComponent property on the DrawerNavigator, this allows us to make custom content for the menu and use the stack navigator to navigate to these pages.  Obviously in this example we made the drawer menu very simple in design but React Native gives you the tools to customize how you would like.

There you have it! A simple React Native application with bottom tab navigation, top tabs, and a hamburger menu.  No matter what direction you would like to take with navigation inside you app React Native gives you the freedom and the ability to create the experience you want.  See the finished product below! For more information on the packages I used check the links below.

 

Caleb Hatcher

Caleb Hatcher

Mobile software engineer with experience in cross-platform solutions such as react-native, flutter, and titanium. Graduated from Randolph Macon in 2016 with a major in Computer Science and a minor in Biology. Started the Shockoe indoor soccer team.

How to Setup Configurations and Schemes in XCode for all Environments

How to Setup Configurations and Schemes in XCode for all Environments

The beginning of any new or existing iOS application development cycle should start off on the right foot. A solid foundation to support each environment level within the configuration of the XCode project is a great first step to the success of your application. This will allow the development team, continuous integration (CI) services, and QA to easily test/create builds for a particular environment.

  • A typical application environment hierarchy may look like:
  • Debug – Used by the development team
  • Development – Lastest approved development source
  • QA / UAT – Latest development source from the previous sprint
  • Stable / Production – Tested and approved source for deployment

Many different aspects of the application can change between environments such as:

  • API host
  • Provisioning Profiles
  • Firebase Project
  • Network debugging tools
  • Development debugging tools
  • Project Bundle Ids
  • Application versions
  • URL Types (Deep / Universal Links, etc)
  • Application Features
  • Other third-party SDK integrations

Ideally, we would like to specify how each of these aspects of the application can change depending on the selected environment. This post is designed to show you how to set up your iOS application to do this. Let’s get started!

Part 0: Let’s Get Started

For the purposes of this post, we will be starting with a blank XCode (10.1) iOS Single View Application. We will be using Swift for this example. Everything we do here can also be tailored for an existing application.

 

  1. Start by opening XCode, and creating a new Xcode project. Use a Single View App as a template.

2. Give the project a Product Name, Team, Organization Name, Organization Identifier, and set the language to Swift.

3. Click Next and save the project in the location of your choice.

Part 1: Configurations

The first part that needs to be taken care of is the creation of different configurations in XCode for each of the environments we want to support. A single environment typically consists of a debug and release configuration depending on the apps needs. To create those configurations we will need to start by defining each configuration.

 

  1. Open the project settings by selecting the project blueprint from the Project Navigator, and then click the blueprint under the Project section.

2. Find the section for Configurations. Using the environments we defined in the intro, we will create these configurations:

  • Debug – 1 Debug configuration
  • Dev – 1 Debug configuration, 1 Release configuration
  • QA – 1 Debug configuration, 1 Release configuration
  • Stable – 1 Debug configuration, 1 Release configuration

The reason for creating 1 Debug and 1 Release configuration is:

  • Debug – Used for running the environment locally for testing by the development team if needed.
  • Release – This is the configuration that will archive the application to be built locally or by CI.

    The single Debug configuration for local development is set up in order to isolate the configuration that should be used by the development team for bug fixing or new features.

3. Start by renaming the existing Debug and Release configurations to “Dev Debug” and “Dev Release”.

4. Next, create the local debug development configuration. Using the ‘+’ action under configurations. Choose to duplicate ‘Dev Debug’ and rename the configuration to Debug.

5. Now create the configurations for QA and Stable. Duplicate the “Dev Debug” and “Dev Release” configurations and rename them accordingly: “QA Debug”, “QA Release”, “Stable Debug”, “Stable Release”. (Make sure to duplicate the corresponding release and debug configuration. This will preserve the default configuration values for Debug and Release configurations)

Part 2: Schemes

The configurations that we just created now need to be associated with an XCode scheme. For more information on what a scheme is, check out the apple documentation reference here. To do so, we need to manage the schemes of the project.

 

  1. Open the scheme manager. Select Product -> Scheme -> Manage Schemes… from the toolbar.

2. By default, only one scheme will show in the list and it was associated with the Debug and Release configurations. We will change this scheme to be the Debug development scheme. Select it from the list and click Edit.

3. For each of the options on the left-hand side, change the Build Configuration to Debug. This will associate all execution types for the Debug scheme to use the Debug configuration. Click ”Manage Schemes” to return to the list of schemes.

4. Next, create a new scheme using the ‘+’ action and name it Dev PROJECT_NAME, where PROJECT_NAME is the name of your project. Click ‘OK’ to create the new scheme.

5. Make sure the scheme is marked as shared in the list of schemes. This will allow other developers to use the scheme and CI will have access to build the scheme.
6. Edit the “Dev PROJECT_NAME” scheme.
7. (Optional) if your project includes Unit and UI Test, add those targets to the list of build targets and select only the test checkbox for each. To add a target, use the ‘+’ action, and select the Unit test and UI test targets. This will allow the scheme to run those test.

8. For each of the build types in the left side panel, change the configuration to the corresponding Debug or Release configuration for that scheme.

9. Repeat steps 4 – 8 for QA and Stable environment
10. Close the scheme manager. Each of the schemes should now be listed under the scheme selector.

At this point, the project is set up with configurations and schemes for each environment. The scheme can easily be changed to set the current environment the project can be run with. Because the schemes are shared, a CI can use these schemes to create a build for that particular environment. The build can also be created locally using the archive utility.

Part 3: Build Settings

The project can easily change environments but we need to actually set up which aspects of the application will change for each. Many of those aspects are defined in build settings and we can see how to change values between environments using the configurations we created for the projects. In particular, let’s look at the build settings for the app target.

 

  1. Open the project settings by selecting the project blueprint from the Project Navigator
  2. Select the Target to configure under the Targets section.
  3. Select the Build Settings Tab.

4. Notice that certain properties in the list of Build Settings can be expanded to show the value for each configuration. This will be used to set the value we want for each.
5. Scroll down or use the search bar to find the property Product Bundle Identifier.
6. Expand the property to view the value for each configuration.
7. Set the Product Bundle Identifier value for each environment. This will allow a unique build of each environment to be installed to a single device at a time. Which improves the testing capabilities for a QA team.

8. Review the rest of the Build Settings to identify other parts of the application target that the application needs to change based on the environment. Some other settings to look at are:

  • Info.plist File
    • Identifies a particular plist file for the environment to build with
  • Product Name
    • Sets the name of the product for QA to more easily identify the environment it was built for.
  • Code signing
    • Change to provisioning profile associated with a build environment. This can be more easily done in the General Tab of the Target settings.
  • Active Compilation Conditions – See next Part
  • Custom User Properties
    • Define custom variables that, such as a bundle version, that can be used within the Info.plist file to change the version based on the environment. The possibilities here are endless.

Part 4: Active Compilation Conditions

Sometimes the application will need to tailor the source code based on the current environment that is being built. For example, if the application wants to include network debugging or other debugging tools for all debug builds. Another example would be removing logs or other unnecessary code for production builds. To do this, the application will need to know what environment is being built from within the source code.

 

  1. Open the Build Setting for the application target (See Part 3, Steps 1 – 3)
  2. Scroll down or search for Active Compilation Conditions
  3. Expand the property to see the values for each environment configuration

4. The DEBUG flag is defined by default, but let’s add some additional flags to identify our other environments and the production environment.
5. Double click on the value of the configuration to expand the editor

6. Use the ‘+’ to add a new value. For the Dev Debug configuration, add DEV.

7. Continue to add additional flags as needed to fit the applications needs. For this tutorial, we will use these flags.

8. Now that the Active Complication Conditions have been configured, we can use these within our code to change which parts are executed based on the current environment.
9. Open the AppDelegate.swift file of the application

10. Add this section of code to didFinishLaunchingWithOptions to see how active compilations conditions can change which parts of the code are executed based on the currently selected scheme.

11. Now, set the Scheme you would like to run and see the appropriate console log for that scheme.
12. Done!

These Active compilation conditions can be used in various ways to change the application for the selected environment, such as:

  • API Host definitions
  • Activating debugging tools
  • Auto-filling form data for testing
  • Bypassing certain screens
  • Selecting different configuration files
  • etc…

 

SHIP IT.

The application is now set up with a solid foundation to tailor any aspect of it for each environment. In review, for each environment we: set up Debug and Release configurations, associated those configurations with a scheme, set up specific build settings values for each configuration, and set Active Compilation Flag that can be used within our source code.

Justin Boswell

Justin Boswell

Justin is a Mobile Software Engineer with a specialization in iOS native development, but he enjoys creating frontend and backend solutions across a wide variety of platforms. When he is not spending his days getting Swifty, he enjoys hanging out with friends, playing soccer, and getting wins in online competitive games. He is a Computer Science graduate from Virginia Commonwealth University and was born and raised in the Richmond area.