Ever since I started developing software, I've had a gravitational pull towards mobile applications in particular. I have dabbled with it on my spare time and released an iOS app written in swift. However, now has come the time where I want to release an actual product and try to monetize it. Part of the preparation of this app is to choose what framework to use, and that is where this blog post comes in.

As an indie developer, I knew that with my limited time it would make sense to utilize a cross-platform framework. Arguably the most popular ones are Xamarin, React Native & Flutter. This might be an unpopular opinion, but I have a distaste for Javascript. And since you write javascript when developing with React Native, that's pretty much out the window. That leaves me with Xamarin and Flutter.

I decided to create a dummy app in both frameworks to get a feel for the development experience. I decided to create a simple bullet list of what the sample apps should contain before I started:

  • Main view with a gradient background
  • A listview with dummy data fetched from https://jsonplaceholder.typicode.com
  • A detail view showing content from the selected listview item

As you probably can tell, this isn't exactly an exhaustive test of what each framework can provide you. But it covers the cornerstones such as navigation, layouts and handling data. I believe this exercise combined with research can provide a general idea of what framework is the best fit for you.

Xamarin

Founded in 2011 and acquired by Microsoft in 2016 the framework has some serious experience and force behind it. Which is a important thing to consider in terms of future development and support. With Xamarin you primarily write C#, a mature and battle-tested language. The UI can be create with either XAML or C#. When developing the dummy app with Xamarin I used Visual Studio For Mac Community Edition (7.7.4).

First things first it's important to know that Xamarin has two different ways of creating mobile apps. Xamarin.iOS/Android and Xamarin.Forms. The latter enables close to 100% code share while the platform-specific variant has its separate UI logic. I decided to use Xamarin.Forms for my experiment as I wanted the highest amount of code sharing in my application. As I started working on the welcome screen I found that Xamarin doesn't offer gradients built in. A little disappointing considering how long the framework has been around. Nevertheless there was a library I could make use of called xfgloss. Then the XAML required to implement the gradient was minimal:

<xfg:ContentPageGloss.BackgroundGradient>
        <xfg:Gradient StartColor="#FF5E62" EndColor="#FF9966" IsRotationTopToBottom="true" />
    </xfg:ContentPageGloss.BackgroundGradient>

While on the topic of XAML, Visual Studio has a preview feature showing your UI as you build it. It redraws the screen whenever you save, but it doesn't take into account any business logic. This feature makes building UIs quicker since you don't have to rebuild your app every time you want to see how your changes affected the output.

The next hurdle was to load JSON data from https://jsonplaceholder.typicode.com and display the results in a listview. This task was relatively straight forward thanks to data binding. Here's how the XAML looks for the listview component:

<ListView x:Name="PostsView" ItemTapped="Handle_ItemTapped">
    <ListView.ItemTemplate>
      <DataTemplate>
        <ViewCell>
           <StackLayout Orientation="Horizontal" Padding="5">
              <Label Text="{Binding Id}" WidthRequest="30" VerticalTextAlignment="Center" /> 
              <Label Text="{Binding Body}" HorizontalTextAlignment="Start" />  
           </StackLayout>             
        </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Pay attention to the x:Name property on the very first line, this enables us to reference the component in the code behind file:

public async Task GetPosts() {

    var client = new HttpClient();
    var content = await client.GetStringAsync("https://jsonplaceholder.typicode.com/posts/");

    PostsView.ItemsSource = JsonConvert.DeserializeObject<ObservableCollection<Post>>(content);
}

And just like that we have a listview with a viewcell for every object in the JSON array. There's obviously some black magic going on behind the scenes, but I'll leave that for another blog entry.

The last task on my list of dummy features was to display a "detail view" of the selected post. I achieved this by simply passing the id of the item tapped to the next view and querying the API for the specific item. In hindsight, I could just have passed the object itself, since we already retrieved it when populating our listview. So there you have it, dummy app #1 complete!

I found developing with Xamarin to be an overall good experience, there were small hick-ups along the way, but finding help was a breeze in a community this large. I did, however, have some issues with the XAML previewer that I wasn't able to resolve. This was mainly issues with one of the views that wouldn't output a preview. I felt like the app I created had good performance and felt snappy, but if performance is a top priority you probably want to go the "native" route and create separate UIs. It's important to note that Xamarin doesn't stop at iOS and Android. It also offers development in macOS, watchOS, tvOS, android wearables, and Tizen. A staggering amount of possibilities for the developers investing in this ecosystem.

By reading this last paragraph you probably think I've already made up my mind about which framework to choose? Well, lets see what Flutter can pull out of its sleeve.

Flutter

Flutter is a new framework hot off the press, developed by Google. It just recently released version 1.0 just in time for Christmas. There has been a lot of praise by seasoned developers for its fast prototyping abilities, and its been receiving a fair deal of hype the last couple of months. But hey, don't take my word for it! Here's a chart showing the amount of interest compared between Flutter and Xamarin for the past year.


Google choose Dart as the programming language powering Flutter. Not a big surprise, since it's their own language. Dart may come across as familiar to many developers, thanks to its unsurprising object orientation and syntax. It certainly holds true for my brief encounter with the language. I come from a C# background and I found that some of my experience was transferable to Dart. That being said, let's have a look at my crack of implementing the dummy app with Flutter and Dart.

So once again, the first task was to create the main view with a gradient background. Flutter has the ability to do this out of the box. There might be several ways of doing this, but I ended up using a BoxDecoration widget that has a gradient property. You can see the implementation below:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          padding: EdgeInsets.all(15.0),
          decoration: BoxDecoration(
              gradient: LinearGradient(stops: [
            0,
            1
          ], colors: [
            Color.fromRGBO(255, 94, 98, 1),
            Color.fromRGBO(255, 153, 102, 1)
          ], begin: Alignment.topCenter, end: Alignment.bottomCenter)),
          child: Row(
            children: [
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [postButton(context)],
              )
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          )),
    );
  }

The example above might seem a little intimidating for someone just starting out, but I swear after building a few widgets it all starts to feel quite natural.

Let's see how Flutter handles networking and deserializing JSON. This was actually the hardest part for me. Maybe because I have been so spoiled by C# and the Newtonsoft.JSON library. All I had to do then was call a simple method and make sure my domain object had the same property names, and magic would ensue. Making the network call with Flutter is pretty intuitive and looks like this:

Future<List<Post>> fetchPosts() async {
  final response =
      await http.get('https://jsonplaceholder.typicode.com/posts/');

  if (response.statusCode == 200) {
    // If the call to the server was successful, parse the JSON
    return parsePosts(response.body);
  } else {
    // If that call was not successful, throw an error.
    throw Exception('Failed to load post');
  }
}

List<Post> parsePosts(String responseBody) {
  final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();

  return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}


On line 7 you can see we call a method called 'parsePosts' which parses the incoming JSON to a list of posts. This however did not feel intuitive to me, but I got a basic understanding of it by reading this great post.

Next we need to populate a listview with our data:

class Posts extends StatelessWidget {
  final Future<List<Post>> posts;

  Posts({this.posts});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
          child: FutureBuilder<List<Post>>(
            future: posts,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return snapshot.hasData
                    ? PostList(posts: snapshot.data)
                    : Center(child: CircularProgressIndicator());
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }
              // By default, show a loading spinner
              return CircularProgressIndicator();
            },
          ),
        ),
      
    );
  }
}

class PostList extends StatelessWidget {
  final List<Post> posts;

  PostList({this.posts});
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Posts")
      ),
      body: ListView.separated(
      itemCount: posts.length,
      itemBuilder: (BuildContext ctxt, int index) {
        return new GestureDetector(
            onTap: () => Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => PostDetail(
                            post: fetchPost(index + 1),
                          )),
                ),
            child: Column(children: <Widget>[
              Padding(
                  padding: EdgeInsets.fromLTRB(10.0, 0, 0, 0),
                  child: Row(
                    children: <Widget>[
                      Expanded(
                        child: Text(posts[index].id.toString()),
                        flex: 1,
                      ),
                      Expanded(
                        child: Text(posts[index].title),
                        flex: 9,
                      )
                    ],
                  )),
            ]));
      },
      padding: EdgeInsets.fromLTRB(0, 10, 0, 10),
      separatorBuilder: (BuildContext context, int index) =>
          Divider(color: Colors.black),
    )
    );
  }
}


The first widget decides what to show based on our network call, if we don't have any data, show a spinner, else display our list. The bulk of the logic lies within the 'PostList' widget, and your instant reaction might be that this seems like a lot more work then with the Xamarin example we looked at earlier. Yes and no would be my answer. Yes, there's more code, but most of it has to do with layout. And the hot-reloading in Flutter is no joke, it makes you really productive.

Last but not least, we have the detail page:

class PostDetailView extends StatelessWidget {
  final Post post;

  PostDetailView({this.post});

  @override
  Widget build(BuildContext context) {
    return Center(
        child: RichText(
            text: TextSpan(
                text: post.title, style: TextStyle(color: Colors.black))));
  }
}


Super basic, just the title of the post nested within a center and text widget.

I have thoroughly enjoyed creating the dummy app with Flutter. It might not have the same size community that Xamarin has (yet) or portability, but the kick-ass developing experience can't be denied. I mentioned earlier that I'm somewhat experienced with C# and the .NET framework. That made the app developing with Xamarin a familiar experience. Flutter and Dart was uncharted territory for me but I was surprised how transferable some of my existing skillsets was. And also how intuitive most of my limited interactions with the framework has been.

Conclusion

First off, let me tell you that I have really enjoyed developing with both frameworks. They both have their strengths and weaknesses, and you will most likely be happy either way you go. But for my own sake, I've already decided the framework for my first app. Let's do some pros and cons for both frameworks before I tell you why I choose what I did.

For Xamarin I would like to highlight the C# language, community and native UI as some of the top features it got going for it. On the negative side, we don't get proper hot-reload functionality, building complex UI often needs 3rd party libraries or custom renderers, and Visual Studio for Mac isn't quite there yet.

Flutters pros are hot-reloading, performance, and productivity. The hot-reloading combined with ready-made UI widgets, makes prototyping crazy fast. My concerns regarding flutter and therefore its cons are amongst other things community size. I expect this to grow rapidly, but as of now, this leads to a lack of 3rd party libraries. Another concern is the custom UI flutter is drawing with Skia. Drawing their own components gives Flutter awesome performance, but is also a concern regarding their ability to keep their components up to date with their native counterparts. I also can't help to think that Google might have a bias towards focusing more heavily on material design than iOS.

All things considered, I'm choosing Flutter for my project, mostly because of the developer experience. Xamarin is the behemoth you can't go wrong with, but Flutter just gives me that fuzzy feeling deep inside. As I'm writing this there are still some crucial components missing in Flutter, such as an in-app-purchase API. But this is being worked on, and I have faith that we will see exponential growth in support and 3rd party libraries in the coming months. For enterprise use, I would, however, recommend Xamarin because of its support and maturity.

The source code for both projects can be found here. Keep in mind I've made no architectural decisions, and just implemented the bare minimum to get the prototype functional.

So there you have it! I hope you found the comparison informative and I would love feedback and input in the comments section below.