Suppose that you wanted to extend the application to show the user
an alert whenever somebody mentions her on Twitter. The logic to check
with Twitter for mentions would ideally remain in the shared layer so that
it can be reused across all platforms. This means that the check needs to
be platform-independent, but each platform still needs to be able to know
when it occurs so that it can notify the user. This is a great example of
a time when the observer pattern discussed in Chapter 3 can come in handy. TwitterClient
can expose an event that it
publishes when a mention is detected, and each application can subscribe
to the event and alert the user.
First, add a new class to the Chapter4 folder named MentionEventArgs
, which will represent the
data sent back to the application when the event is fired. It should
include a Tweet
object (the same type
created in the first section) containing information about the mention
(see Example 4-13).
Example 4-13. MentionEventArgs.cs
using System; namespace SharedLibrary.Chapter4 { public class MentionEventArgs : EventArgs { public Tweet Tweet { get; private set; } public MentionEventArgs(Tweet tweet) { Tweet = tweet; } } }
Now open up TwitterClient.cs and modify it to look like Example 4-14. The example only includes new code being added to the class, so append this to what is already in that class.
Example 4-14. TwitterClient.cs (updates only)
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading; using System.Xml.Linq; namespace SharedLibrary.Chapter4 { public class TwitterClient { public event EventHandler<MentionEventArgs> MentionReceived; public TwitterClient() { new Timer(delegate { var mention = new Tweet { Id = 42, CreatedAt = DateTime.Now, Text = "This is a fake mention" }; if (MentionReceived != null) { MentionReceived(this, new MentionEventArgs(mention)); } }, null, 15 * 1000, Timeout.Infinite); } // ...code from last section... } }
Define the
MentionReceived
event, supplyingMentionEventArgs
as its argument type.In the constructor, start a timer to pretend a mention is received.
Create a fake mention, assigning values for its properties.
If there are any subscribers to the event, publish the event to them.
Set the timer to fire once after 15 seconds.
To keep things simple, this example uses a Timer
to fake the event of receiving a mention
instead of getting bogged down in Twitter specifics. Fifteen seconds
after the instance of TwitterClient
is created, the timer will elapse and any subscribers to the event will
be notified that a mention was received. Each application is then free
to notify the user in any way it wants, allowing for fully native
behavior. Add links to both of these files in all three platform-shared
library projects.
Open up TwitterViewController.cs and attach a handler
to the client’s MentionReceived
event
in the ViewDidLoad()
method. When the
event is received, show a new UIAlertView
containing the tweet’s text (see
Example 4-15). Remember
that the callback will happen on a background thread, so be sure to show
the alert back on the UI thread. When you run the application and the
timer elapses, it should look like Figure 4-5.
Example 4-15. TwitterViewController.cs (updates only)
using MonoTouch.UIKit; using SharedLibrary.Chapter4; namespace Chapter4.MonoTouchApp { public class TwitterViewController : UITableViewController { public override void ViewDidLoad() { // ...code from last section... _client.MentionReceived += (object sender, MentionEventArgs args) => { InvokeOnMainThread(() => new UIAlertView("Mention Received", args.Tweet.Text, null, "Ok", null).Show()); }; } } }
Back in the Android application, modify TwitterActivity
and attach a handler to the
client’s MentionReceived
event in
OnCreate()
. When the event is fired,
show an alert dialog with the tweet’s text (see Example 4-16), making sure to
do it on the UI thread. Running the application should result in
something similar to Figure 4-6.
Example 4-16. TwitterActivity.cs (updates only)
using Android.App; using Android.OS; using Android.Widget; using SharedLibrary.Chapter4; namespace Chapter4.MonoAndroidApp { [Activity (Label = "\\@OReillyMedia", MainLauncher = true)] public class TwitterActivity : Activity { protected override void OnCreate(Bundle bundle) { // ...code from last section... client.MentionReceived += (object sender, MentionEventArgs args) => { RunOnUiThread(() => { new AlertDialog.Builder(this) .SetTitle ("Mention Received") .SetMessage(args.Tweet.Text) .SetPositiveButton("Ok", delegate { }) .Show(); }); }; } } }
Lastly, in the Windows Phone application, open MainPage.xaml.cs. In the OnNavigatedTo()
method, show a message box when
a mention is received, again being careful to execute the code on the UI
thread. Running the application in the emulator should look like Figure 4-7.
Example 4-17. MainPage.xaml.cs (updates only)
using System.Windows; using System.Windows.Controls; using Microsoft.Phone.Controls; using SharedLibrary.Chapter4; namespace Chapter4.WindowsPhoneApp { public partial class MainPage : PhoneApplicationPage { protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { // ...code from last section... client.MentionReceived += delegate(object sender, MentionEventArgs args) { Deployment.Current.Dispatcher.BeginInvoke(() => { MessageBox.Show(args.Tweet.Text, "Mention Received", MessageBoxButton.OK); }); }; } } }
Get Mobile Development with C# now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.