Getting Started with Metro – A Twitter Trend Reader (p1)

Its not only because I went to the Windows 8 Developer Event yesterday, I have honestly been meaning to dive into the new features in Windows 8 and take a crack at designing apps with Metro in mind.  With that I elected to spend the majority of today working with Windows 8 and attempting to create a simple app I came up with.

Twitter tracks trends and the trends are tracked for a few select cities around the world.  I wanted to create an application that would allow users to see the full list of countries with cities in which a particular trend is being tracked.  Group these “trends” by the country and allow users to dive further in and see the relevant tweets for the particular trend.  Very simple.

Obviously the starting point for this endeavor was getting the software.  I actually installed Windows 8 on an old Tablet that I bought back before my study abroad in Japan in 2006.  I wondered if I could interact with it using the pen.  I havent used the machine for anything serious in many years.  As you might expect, the pen didn’t work and I really came to find that Windows 8 really doesn’t belong on this system, but I didn’t want to take time to install it side by side on my IBM personal laptop.

First thoughts

Ok, I will say it, the Microsoft guys really make this stuff seem easier in demos then it actually is.  First, using async and await keywords.  I have been to many talks on this new language feature but actually doing it does take more thought then I initially thought.

protected async override void OnNavigatedTo(NavigationEventArgs e)
{
     var locations = await GetLocations();
     var data = await GetAvailableTrends(locations);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The async keyword essentially indicates that a method should not block the UI thread.  Once the method features this keyword, you can use the await keyword.  How this has been explained to me is that await indicates the result may not be readily available, but it promises that it will be.  Thus any code that needs this result should wait.  In essence, the compiler will rewrite this code to use the TPL.  Code that is dependent on the result will in essence be place in a “continuation”.  Since both of these methods will make a web request, it is important that they both “await” the return.

Honestly, this can be confusing, as you will see, understanding how to use async and await will be critical moving forward.  It really does make things easy, but you do have to make sure you don’t rely too much on the “await”.  I found it useful to break things up into methods and mark those with await.  Remember, you can only “await” an “async” method.

Making Requests

To actually get the data, we need to make some requests, and we can use the brand new (I think) JSON handling objects in Windows.Data.

 

   1:  private async Task<List> GetLocations()
   2:  {
   3:      var request = WebRequest.CreateHttp(
   4:          "https://api.twitter.com/1/trends/available.json");
   5:      var response = await request.GetResponseAsync();
   6:   
   7:      using (var stream = response.GetResponseStream())
   8:      {
   9:          var content = new StreamReader(stream).ReadToEnd();
  10:          var locations = from jo in JsonArray.Parse(content)
  11:                                          .Select(jo => jo.GetObject())
  12:                          select new
  13:                          {
  14:                              WoeId = int.Parse(jo["woeid"].Stringify()),
  15:                              Country = jo["country"].Stringify()
  16:                          };
  17:   
  18:          var groupings = (from location in locations
  19:                           where location.Country.Length > 3
  20:                           group location by location.Country into g
  21:                           orderby g.Key
  22:                           select new TrendLocation
  23:                           {
  24:                               LocationName = g.Key,
  25:                               LocationIds = g.Where(t => t.WoeId > 1)
  26:                                              .Select(t => t.WoeId).ToList()
  27:                           }).ToList();
  28:   
  29:          return groupings;
  30:      }
  31:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Sorry, that is a lot of code.  What I really want to draw attention to is line #10, the rest of this is fairly select explanatory. Since we know what is coming back from Twitter is a JSON array (even if it might only have one result), thus we parse it as such.

Working with these new library is, quite frankly, a royal pain in the ass. First understand that each entry in the JsonArray is actually a JsonObject, but you cant run Cast, so you need to do a Select.  Next, once you have the object, you can use [] notation to reference the key you want.  This comes back as an IJsonValue. Depending on what is actually at the location you must call the appropriate method.  Above, I am calling Stringify which makes no sense to me, but I could never get GetString to work.

Its not that the library is necessarily bad or broken, it just feels weird.  I don’t like all the casting and the knowledge my code must have about what is coming back.  This part took me the longest to decipher.

Where Am I now?

At present I am nearly to the point where I have all of the data for display.  However, I am running into problems, I believe, with rate limiting on Twitter, because I am making so many requests so frequently.  I will need to find a way to cut down on the amount of traffic I am producing.  I am hoping,in a future entry, to talk about using the GridView to actually create the UI, which is, in my mind, the most alluring part of Windows 8.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s