Developing a Mobile app using MVIS
by Andrew Gorovoy
Even 5 years ago, buying items online from a mobile browser or app was uncommon. Now, the average American spends close to three hours every day using their mobile device for activities ranging from shopping to communication to entertainment. Many daily tasks revolve around our phones, and businesses know this — annual mobile app revenue is estimated to approach $200 billion. With consumers’ hurried transition to mobile everything, businesses need to catch up, even businesses with legacy code bases and archaic technologies.
In my previous blog post, I detailed my development experience using the MultiValue Integration Server (MVIS) to produce a modern web application. Before continuing, I highly recommend you give that post a quick read, but I’ll still provide a short refresher. MVIS is a tool that encapsulates the robust MultiValue (MV) database interactions and provides easily consumable RESTful endpoints and detailed documentation with a testing environment using Swagger. In my previous project, I had no idea what MV was or how to use it; however, with MVIS, the detailed documentation and modern RESTful API provided a clean and straightforward development experience. I built a web app in a week using modern front-end web technologies. The development process was really enjoyable, and I was curious if this experience would translate to mobile. So, I pitched the idea to develop a mobile MVIS example, and I got the green light.
Before I began coding, I wanted to do some research on the general state and direction of mobile technologies. For those unfamiliar with mobile development, the two biggest mobile operating systems are Android and iOS (Apple). Together, these two platforms make up close to 98% of mobile phones on the market. What does that mean for mobile apps? A mobile app needs to run smoothly on both Android and iOS devices to provide value for all your customers, or at least 98% of them. This can be done using three different mobile app development approaches.
Native apps are like native desktops apps. They are written to be platform specific. This provides great performance and native API access like Contacts or Bluetooth; however, it also means building two separate code bases: one for each respective mobile OS. Two code bases mean twice the maintenance which means twice the labor. This is often an option if there are plenty of resources and time to market is not critical.
I have a tough time calling hybrid apps mobile apps. Hybrid apps are nothing more than web apps in mobile wrappers. There are some pros and cons to this approach. Hybrid apps use common web technologies, so finding talent is not a problem. And cost savings are enormous when compared to native development since hybrid apps work cross platform. Using mobile wrappers, a single code base can be deployed to iOS, Android, and the web. Unfortunately, performance and user experience does not compare to native applications. Hybrid apps are known to be significantly slower than native applications. In addition, they will look and feel like mobile websites rather than applications. This can have an adverse effect on your customers who are used to smooth and platform centric user interfaces and experiences.
Cross Platform App
This paradigm of mobile development is a recent innovation. It is an attempt to mix the benefits of native and hybrid apps. Cross platform apps are native apps, usually built on top of some sort of platform engine that compiles source code in platform specific bundles. Cross platform app performance nears the speed of native applications; however, the extra layer still inflates the package size and drags down performance, but still outshines hybrid app performance. Cross platform apps rely on a single code base, which means significant labor and cost savings. However, these cross-platform technologies, to optimize performance, already handle many user interactions and component styling. Therefore, creating truly custom brand specific experiences requires some serious effort.
How it works
Flutter apps are built on widgets. Everything is a widget from buttons to gestures to text. This provides a logical framework of development. For example, a container has a raised button with text which has an action widget when it is pressed. It works on a nested structure.
My objective was to recreate the mock streaming service from my previous project in mobile form. My first step was to figure out the architecture and class structure of the application. I describe the app functionality in detail in my previous blog post; however, for a quick overview, the app should be able to display all the movies sitting in the MV database. The movies should be filterable and searchable, and there should be a way to show specific information on a movie and save it for later.
My first step was building out a simple UI for testing and development purposes. I knew I needed two screens. One that shows all the movies, and a screen for showing specific information on a movie.
Now came the fun part, connecting the UI to MVIS. Dart is asynchronous in nature. Other functions can execute while some function is waiting for a response. Therefore, I defined a synchronous function also known as a Future in Dart to call to MVIS. While that call is happening, the rest of the screen is being rendered. As soon as MVIS responds, the data is passed to a MovieCollection class object. This object takes the JSON, decodes it, creates a Movie object for each movie in the JSON data, and stores it in the MovieCollection instance. Flutter is a state based rendering engine; once the data is available, the screen is rendered, but this time the list is populated with movies.
I continued development by focusing on the screen that provides specific movie info. This was pretty straightforward. Each movie displayed in the list is a Movie object. A Movie object holds all the necessary info on that movie, so when a list tile is tapped, the app renders a new page, and displays all the information with the associated Movie object instance. To the movie info page, I then added two buttons: “Watch Now” and “Save for Later”. I will discuss adding functionality to these later in the post.
Now, I wanted to add the ability to filter movies. This was done using MVIS calls. Using some simple widgets, I added a side panel with different filtering options. When one of these filter buttons is tapped, a call is made to MVIS, but this time the associated filter is added as a URL with query parameters. The response is then decoded, turned into Movie objects, and then re-rendered. The Swagger documentation that comes with MVIS provides examples and the ability to test calls to confirm request validity which was very helpful.
Now, the last big feature I had to implement was the Save for Later system. This task was not as straightforward as I had imagined. The first iteration simply added “Saved Movies” to a local array. However, as I learned more about the Flutter framework, I realized that anytime a page is loaded, data associated with it is also redefined, so the array was being cleared anytime a user left the main page. I started thinking about ways to maintain data persistence. This is where some of the issues with MVIS began to show themselves. An ideal solution would be to add a boolean isSaved value to the data model and send a POST request back to MVIS anytime a movie is saved. Then, rendering saved movies would be as simple as an MVIS call. However, MVIS is a one-way street**, and nothing on the database side can be manipulated by MVIS. Personally, I have no knowledge of MV databases, and trying to learn BASIC was a scary thought, so developing workarounds was the only option.
In the end, I was able to create a copy of the saved movies before the array is cleared using a page rebuild and cloning the array. I realize it may not be the most efficient solution, but ,hey, it gets the job done.
With that, the majority of the app had been implemented. Looking back at my development experience, MVIS worked like a charm. Aside from not being able to POST and manipulate the data models, MVIS didn’t influence the way I built the app. I could follow recommended protocol, and MVIS integrated perfectly. The biggest hurdle was learning Dart and getting comfortable with the Flutter SDK. In general, mobile development proved to be a very enjoyable experience. I have heard many whine and groan about mobile development but working with Flutter made it a straightforward process. I am excited for mobile technologies looking forward, and I believe MVIS and Flutter could be a highly capable technical architecture for legacy enterprises looking to go mobile. Thanks for reading this post. Check out the screen recording to see how the app works live.
** NOTE: MVIS actually is capable of more than just the one-way type operation: MVIS uses the POST or PUT methods to provide update capabilities to the database. We purposely designed Andrew’s experience with MVIS to be completely unassisted as we really wanted to get his candid feedback on his experiences. We wanted to publish his blog post in his own words, and provide clarity into his experience and into MVIS’s capabilities.
So, how does one accomplish what Andrew wanted to achieve? The solution requires a little more than just updating the data model with an isSaved value. The reason being, multiple users would need to maintain their own data. But having an isSaved field in the data model would mean that the Boolean would be saved against the data file itself, and not on a per-user basis. So, the end solution would probably entail creating a second file for user-specific data. – Zain Master, Rocket Software Sr. Product Manager