Featured image of post Updating RPN Radio Mobile App

Updating RPN Radio Mobile App

Version 2.0 coming soon




Update 1

2022-03-31

I just refactored the FutureBuilder by separating the future tasks to where they are actually used in the UI - to prevent long startup and show the main UI at launch instead of a loading screen.

Version 2.0.1 is now on open testing for Android on Google Play Store.

Download link: RPN Radio for Android (Beta)


It’s been a while since I coded and updated my apps, it just somehow began again when I felt the urge to refresh my website’s looks. Now I am aiming to light up every Github contribution grid block whenever I can.

Updating Flutter Packages

The first thing I did was to check for updated packages from pub.dev by using flutter pub upgrade

Then most are already outdated and forced some to major versions withflutter pub upgrade –major-versions

Also, I tried to use Android Studio for Flutter programming and it took a little while again to get used to keyboard shortcuts coming from VS Code.

Like the usual Alt + Shift + F to format code, now I have to use two hands for Ctrl + Shift + L. Also the shortcut for navigating to implementations F12 on VS Code, it’s now Ctrl + Alt + B. Heck, I can’t be bothered wasting time to remap those shortcut keys…

Despite the hassle above, Flutter coding in Android Studio also has awesome perks like: better debugging, better error checking by highlighting files with errors, faster navigation to files, assets manager and Intellisense. Though Android SDK management is still a pain in the a**. Change my mind.

New Code

My project files were all over the place, so I finally bothered to refactor some files to proper folders like putting model classes to a model folder, services to services folder, etc.

Refactoring files to folders

Refactoring files to folders

Upgrading packages with at least 3 versions above since the app’s last update brought so much changes. Honestly I followed this open source project (Flutter Audio Service Demo) from GitHub and slightly modified/refactor the codes to minimize and actually use the code my app will only use.

Futures

I also updated the app with a new feature to fetch sponsors' ad placement images from a URL then view them when they are actually present in the contract - I used JSON to fetch the data. I faced a problem decoding it when I faced this unfamiliar type Map<String, dynamic> coming from a C# perspective.

I managed to get it to work but a new issue appeared, two tasks are being awaited even the UI is now visible which made two variables null when they are still being done, making some unwanted behaviors.

Then I finally used a Future Builder, it basically waits my tasks to finish fetching data before showing the main UI preventing further actions that require the variables.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
return FutureBuilder(
  future: Future.wait([isLiveList(), getImages()]),
  builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
  if (snapshot.hasData) {
    final liveList = snapshot.data[0];
    final adsList = snapshot.data[1];
    return MainUI(); // Omitted for brevity
  } else {
    return loadingScreen(); // Omitted for brevity
  }
});

ExpansionList and Swiper

Now I need to add a feature for the app to show a carousel/auto-scrolling of images after being checked if it’s on the database - now it’s based off a .json file.

As stated above, I don’t know if Flutter/Dart preferred indexing a List by using a Map and not a number-index. So I poorly crammed the codes online to fetch the json, decode to objects, index, and list the image names.

1
2
3
4
5
6
7
8
9
Future<Map<String, dynamic>> getImages() async {
  Map<String, dynamic> values;
  final response = await http.get(Uri.parse("https://...ads.json"));
  if (response.statusCode == 200) {
    // If the call to the server was successful, parse the JSON
    values = json.decode(response.body);
    return values;
  }
}

Before adding the view though, I thought heavily on where to put it avoiding the user to a second page. Somehow this is what I went for:

Sponsors View using ExpansionTile and Swiper

Sponsors View using ExpansionTile and Swiper

Sponsors View using ExpansionTile and Swiper

I used ExpansionTile to allow the users to collapse/expand the view and Swiper to show an auto-scroll of the images.

Here’s the code for the Sponsors UI:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
ExpansionTile(
  title: Text(
    'Sponsors',
  ),
  textColor: Colors.white,
  collapsedTextColor:
    Colors.white,
  iconColor: Colors.white,
  children: [
    Padding(
      padding:
        EdgeInsets.only(bottom: 20.0),
          child:
            ConstrainedBox(
                constraints: new BoxConstraints.loose(
                   new Size(MediaQuery.of(context).size.width, 280.0)),
                child:
                new Swiper(
                  autoplay: true,
                  autoplayDelay: 10000,
                  itemBuilder: (BuildContext context, int index) {
                    return CachedNetworkImage(
                      imageUrl: imageUrl,
                      fit: BoxFit.fitHeight,
                      width: MediaQuery.of(context).size.width * 0.60,
                    );
                  },
                  itemCount: adsList[stationNames[_nowPlayingIndex]].length,
                  pagination: new SwiperPagination(),
    ))),
  ],
)

To-Do

It’s hard work but I would look to further clean and optimize the code.

  • Do not use Swiper when image list is only 1
  • Improve loading screen during FutureBuilder
  • Handle “offline” connection

Share this: