WeatherInformation WP8: many improvements
authorgu.martinm@gmail.com <gu.martinm@gmail.com>
Mon, 11 Aug 2014 22:49:59 +0000 (00:49 +0200)
committergu.martinm@gmail.com <gu.martinm@gmail.com>
Mon, 11 Aug 2014 22:49:59 +0000 (00:49 +0200)
WindowsPhone/WeatherInformation/WeatherInformation/App.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/MainPage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/MapPage.xaml.cs
WindowsPhone/WeatherInformation/WeatherInformation/Model/Location.cs
WindowsPhone/WeatherInformation/WeatherInformation/Model/Services/ServiceParser.cs
WindowsPhone/WeatherInformation/WeatherInformation/ViewModels/MainViewModel.cs

index 0d1fb52..dfda732 100644 (file)
@@ -112,6 +112,79 @@ namespace WeatherInformation
             }
         }
 
+        public bool IsStoredDataFresh()
+        {
+            // Check to see if the data is fresh.
+            // This example uses 30 seconds as the valid time window to make it easy to test. 
+            // Real apps will use a larger window.
+
+            // Check the time elapsed since data was last saved to isolated storage.
+            TimeSpan TimeSinceLastSave = TimeSpan.FromSeconds(0);
+            if (IsolatedStorageSettings.ApplicationSettings.Contains("DataLastSavedTime"))
+            {
+                DateTime dataLastSaveTime = (DateTime)IsolatedStorageSettings.ApplicationSettings["DataLastSavedTime"];
+                TimeSinceLastSave = DateTime.Now - dataLastSaveTime;
+            }
+
+            if (TimeSinceLastSave.TotalSeconds < 30)
+            {
+                return true;
+            }
+
+            return false;
+        }
+
+        public WeatherData GetIsolatedStoredData()
+        {
+            string JSONRemoteCurrentWeather = null;
+            string JSONRemoteForecastWeather = null;
+            string city = null;
+            string country = null;
+
+            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
+            {
+                if (isoStore.FileExists("JSONRemoteCurrentWeatherFile.txt") &&
+                    isoStore.FileExists("JSONRemoteForecastWeatherFile.txt") &&
+                    isoStore.FileExists("CityFile.txt") &&
+                    isoStore.FileExists("CountryFile.txt"))
+                {
+                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
+                    using (StreamReader sr = new StreamReader(file))
+                    {
+                        // This method loads the data from isolated storage, if it is available.
+                        JSONRemoteCurrentWeather = sr.ReadLine();
+                    }
+
+                    using (IsolatedStorageFileStream file = isoStore.OpenFile("CityFile.txt", FileMode.Open))
+                    using (StreamReader sr = new StreamReader(file))
+                    {
+                        // This method loads the data from isolated storage, if it is available.
+                        city = sr.ReadLine();
+                    }
+
+                    using (IsolatedStorageFileStream file = isoStore.OpenFile("CountryFile.txt", FileMode.Open))
+                    using (StreamReader sr = new StreamReader(file))
+                    {
+                        // This method loads the data from isolated storage, if it is available.
+                        country = sr.ReadLine();
+                    }
+                }
+            }
+
+            if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather))
+            {
+                // TODO: I am repeating this code 2 times. What could I do to improve it?
+                var parser = new ServiceParser(new JsonParser());
+                var weatherData = parser.WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
+                weatherData.City = city ?? "";
+                weatherData.Country = country ?? "";
+
+                return weatherData;
+            }
+
+            return null;
+        }
+
         // no way of moving temporary file atomically with IsolatedStorageFile. LINUX OWNS MICROSOFT.
         private void SaveDataToIsolatedStorage(string fileName, string value)
         {
@@ -154,8 +227,6 @@ namespace WeatherInformation
             }
         }
 
-
-
         // Código para ejecutar cuando la aplicación se inicia (p.ej. a partir de Inicio)
         // Este código no se ejecutará cuando la aplicación se reactive
         private void Application_Launching(object sender, LaunchingEventArgs e)
@@ -179,19 +250,33 @@ namespace WeatherInformation
             // Check to see if the key for the application state data is in the State dictionary.
             string JSONRemoteForecastWeather = null;
             string JSONRemoteCurrentWeather = null;
+            string city = null;
+            string country = null;
             if (PhoneApplicationService.Current.State.ContainsKey("JSONRemoteForecastWeather") &&
-                PhoneApplicationService.Current.State.ContainsKey("JSONRemoteCurrentWeather"))
+                PhoneApplicationService.Current.State.ContainsKey("JSONRemoteCurrentWeather") &&
+                PhoneApplicationService.Current.State.ContainsKey("City") &&
+                PhoneApplicationService.Current.State.ContainsKey("Country"))
             {
                 // If it exists, assign the data to the application member variable.
                 JSONRemoteForecastWeather = PhoneApplicationService.Current.State["JSONRemoteForecastWeather"] as string;
 
                 // If it exists, assign the data to the application member variable.
                 JSONRemoteCurrentWeather = PhoneApplicationService.Current.State["JSONRemoteCurrentWeather"] as string;
+
+                // If it exists, assign the data to the application member variable.
+                city = PhoneApplicationService.Current.State["City"] as string;
+
+                // If it exists, assign the data to the application member variable.
+                country = PhoneApplicationService.Current.State["Country"] as string;
             }
             
             if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather))
             {
-                weatherData = WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
+                // TODO: I am repeating this code 2 times. What could I do to improve it?
+                var parser = new ServiceParser(new JsonParser());
+                weatherData = parser.WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
+                weatherData.City = city ?? "";
+                weatherData.Country = country ?? "";
             }
 
             ApplicationDataObject = weatherData;
@@ -211,6 +296,8 @@ namespace WeatherInformation
                 if (!string.IsNullOrEmpty(weatherData.JSONRemoteCurrent) &&
                     !string.IsNullOrEmpty(weatherData.JSONRemoteForecast))
                 {
+                    // TODO: too many files? Remember there is a time limit for running this method!!! :/
+
                     // Store it in the State dictionary.
                     PhoneApplicationService.Current.State["JSONRemoteForecastWeather"] = weatherData.JSONRemoteForecast;
 
@@ -223,6 +310,18 @@ namespace WeatherInformation
                     // Also store it in isolated storage, in case the application is never reactivated.
                     SaveDataToIsolatedStorage("JSONRemoteCurrentWeatherFile.txt", weatherData.JSONRemoteCurrent);
 
+                    // Store it in the State dictionary.
+                    PhoneApplicationService.Current.State["City"] = weatherData.City;
+
+                    // Also store it in isolated storage, in case the application is never reactivated.
+                    SaveDataToIsolatedStorage("CityFile.txt", weatherData.City);
+
+                    // Store it in the State dictionary.
+                    PhoneApplicationService.Current.State["Country"] = weatherData.Country;
+
+                    // Also store it in isolated storage, in case the application is never reactivated.
+                    SaveDataToIsolatedStorage("CountryFile.txt", weatherData.Country);
+
                     IsolatedStorageSettings.ApplicationSettings["DataLastSavedTime"] = DateTime.Now;
                 }
             }
@@ -240,16 +339,24 @@ namespace WeatherInformation
                 if (!string.IsNullOrEmpty(weatherData.JSONRemoteForecast) &&
                     !string.IsNullOrEmpty(weatherData.JSONRemoteCurrent))
                 {
+                    // TODO: too many files? Remember there is a time limit for running this method!!! :/
+
                     // Also store it in isolated storage, in case the application is never reactivated.
                     SaveDataToIsolatedStorage("JSONRemoteForecastWeatherFile.txt", weatherData.JSONRemoteForecast);
 
                     // Also store it in isolated storage, in case the application is never reactivated.
                     SaveDataToIsolatedStorage("JSONRemoteCurrentWeatherFile.txt", weatherData.JSONRemoteCurrent);
 
+                    // Also store it in isolated storage, in case the application is never reactivated.
+                    SaveDataToIsolatedStorage("CityFile.txt", weatherData.City);
+
+                    // Also store it in isolated storage, in case the application is never reactivated.
+                    SaveDataToIsolatedStorage("CountryFile.txt", weatherData.Country);
+
                     IsolatedStorageSettings.ApplicationSettings["DataLastSavedTime"] = DateTime.Now;
                 }
             }
-        }     
+        }
 
         // Código para ejecutar si hay un error de navegación
         private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
index a7e3d63..9a9658c 100644 (file)
@@ -44,7 +44,6 @@ namespace WeatherInformation
             // Connect to the database and instantiate data context.
             _locationDB = new LocationDataContext(LocationDataContext.DBConnectionString);
 
-            _locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
             // Código de ejemplo para traducir ApplicationBar
             //BuildLocalizedApplicationBar();
         }
@@ -70,6 +69,8 @@ namespace WeatherInformation
             // and it has remained in memory, this value will continue to be false.
             _isNewPageInstance = false;
 
+            _locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
+
             UpdateApplicationDataUI();
         }
 
@@ -79,6 +80,7 @@ namespace WeatherInformation
             base.OnNavigatedFrom(e);
 
             // Save changes to the database.
+            // TODO: How does DataContext work? How does it know what data was modified? Is it wasting memory? :(
             _locationDB.SubmitChanges();
 
             // No calling _locationDB.Dispose? :/
@@ -96,7 +98,10 @@ namespace WeatherInformation
             // set the page's data object from the application member variable.
             // TODO: I am setting and getting ApplicationDataObject from different threads!!!! What if I do not see its last value? Do I need synchronization? :/
             WeatherData weatherData = (Application.Current as WeatherInformation.App).ApplicationDataObject;
-            if (weatherData != null && !_locationItem.IsNewLocation && IsStoredDataFresh())
+            if (weatherData != null &&
+                !_locationItem.IsNewLocation &&
+                // TODO: NO ESTOY USANDO GetIsolatedStoredData!!!!!! :(
+                (Application.Current as WeatherInformation.App).IsStoredDataFresh())
             {
                 UpdateUI();
             }
@@ -132,11 +137,7 @@ namespace WeatherInformation
 
                 _mainViewModel.LoadData(weatherData);
 
-                var locationItem = _locationDB.Locations.Where(location => location.IsSelected).FirstOrDefault();
-                if (locationItem != null)
-                {
-                    locationItem.IsNewLocation = false;
-                }           
+                _locationItem.IsNewLocation = false;        
             }
         }
 
@@ -151,28 +152,11 @@ namespace WeatherInformation
             NavigationService.Navigate(new Uri(uri, UriKind.Relative));
         }
 
-        public void GetDataAsync()
-        {
-            // Call the GetData method on a new thread.
-            // TODO: Are there too many threads? HttpClient is going to create more... (threadpools and stuff like that...)
-            Thread t = new Thread(new ThreadStart(GetData));
-            t.Start();
-        }
-
-        async private void GetData()
+        async private void GetDataAsync()
         {
-            // Check to see if data exists in storage and see if the data is fresh.
-            WeatherData weatherData = GetIsolatedStoredData();
-
-            if ((weatherData != null) && IsStoredDataFresh() && !_locationItem.IsNewLocation)
-            {
-                (Application.Current as WeatherInformation.App).ApplicationDataObject = weatherData;
-            }
-            else
-            {
-                // Otherwise, it gets the data from the web.
-                (Application.Current as WeatherInformation.App).ApplicationDataObject = await LoadDataAsync();
-            }
+            // Gets the data from the web.
+            // TODO: multiple threads writing/reading same data :(
+            (Application.Current as WeatherInformation.App).ApplicationDataObject = await LoadDataAsync();
         }
 
         /// <summary>
@@ -196,93 +180,8 @@ namespace WeatherInformation
                 AppResources.APIVersionOpenWeatherMap, latitude, longitude, resultsNumber);
             string JSONRemoteCurrentWeather = await httpClient.GetWeatherDataAsync(formattedCurrentURL);
 
-            return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
-        }
-
-        // ESTE METODO ERA PARA CARGAR LOS DATOS JSON NO LOS DE LA BASE DE DATOS. HAY QUE REPENSAR ESTO :(
-        private bool IsStoredDataFresh()
-        {
-            // Check to see if the data is fresh.
-            // This example uses 30 seconds as the valid time window to make it easy to test. 
-            // Real apps will use a larger window.
-
-            // Check the time elapsed since data was last saved to storage.
-            DateTime dataLastSaveTime = _locationItem.StoredTime;
-            TimeSpan timeSinceLastSave = DateTime.Now - dataLastSaveTime;
-
-            if (timeSinceLastSave.TotalSeconds < 30)
-            {
-                return true;
-            }
-
-            return false;
-        }
-
-        private WeatherData GetIsolatedStoredData()
-        {
-            string JSONRemoteCurrentWeather = null;
-            string JSONRemoteForecastWeather = null;
-
-            using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication())
-            {
-                if (isoStore.FileExists("JSONRemoteCurrentWeatherFile.txt") &&
-                    isoStore.FileExists("JSONRemoteForecastWeatherFile.txt"))
-                {
-                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
-                    using (StreamReader sr = new StreamReader(file))
-                    {
-                        // This method loads the data from isolated storage, if it is available.
-                        JSONRemoteCurrentWeather = sr.ReadLine();
-                    }
-
-                    using (IsolatedStorageFileStream file = isoStore.OpenFile("JSONRemoteCurrentWeatherFile.txt", FileMode.Open))
-                    using (StreamReader sr = new StreamReader(file))
-                    {
-                        // This method loads the data from isolated storage, if it is available.
-                        JSONRemoteForecastWeather = sr.ReadLine();
-                    }
-                }
-            }
-
-            if (!string.IsNullOrEmpty(JSONRemoteCurrentWeather) && !string.IsNullOrEmpty(JSONRemoteForecastWeather))
-            {
-                return WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
-            }
-
-            return null;
-        }
-
-        private ForecastWeather ForecastWeatherParser(string remoteForecastWeatherData)
-        {
-            ServiceParser parser = new ServiceParser(new JsonParser());
-            return parser.GetForecastWeather(remoteForecastWeatherData);
-        }
-
-        private CurrentWeather CurrentWeatherParser(string remoteCurrentWeatherData)
-        {
-            ServiceParser parser = new ServiceParser(new JsonParser());
-            return parser.GetCurrentWeather(remoteCurrentWeatherData);
-        }
-
-        private WeatherData WeatherDataParser(string JSONRemoteForecastWeather, string JSONRemoteCurrentWeather)
-        {
-            if (string.IsNullOrEmpty(JSONRemoteForecastWeather))
-            {
-                throw new ArgumentException("Missing argument", "JSONRemoteForecastWeather");
-            }
-            if (string.IsNullOrEmpty(JSONRemoteCurrentWeather))
-            {
-                throw new ArgumentException("Missing argument", "JSONRemoteCurrentWeather");
-            }
-
-            return new WeatherData
-            {
-                JSONRemoteCurrent = JSONRemoteCurrentWeather,
-                JSONRemoteForecast = JSONRemoteForecastWeather,
-                RemoteCurrent = CurrentWeatherParser(JSONRemoteCurrentWeather),
-                RemoteForecast = ForecastWeatherParser(JSONRemoteForecastWeather),
-                WasThereRemoteError = false
-            };
+            var parser = new ServiceParser(new JsonParser());
+            return parser.WeatherDataParser(JSONRemoteForecastWeather, JSONRemoteCurrentWeather);
         }
 
         private void Location_Click(object sender, EventArgs e)
index b6320db..1c1575a 100644 (file)
@@ -26,6 +26,9 @@ namespace WeatherInformation
     {
         // Data context for the local database
         private LocationDataContext _locationDB;
+        // TODO anything better than these two instance fields? :(
+        private string _city;
+        private string _country;
 
         public MapPage()
         {
@@ -143,6 +146,8 @@ namespace WeatherInformation
             // TODO: What if there is no city or country. Is there null value or empty string?
             string cityCountry = String.Format(CultureInfo.InvariantCulture, "{0}, {1}", city, country);
             this.LocationTextCityCountry.Text = cityCountry;
+            _city = city;
+            _country = country;
             // Add the MapLayer to the Map.
             this.mapWeatherInformation.Layers.Add(myLocationLayer);
         }
@@ -174,13 +179,14 @@ namespace WeatherInformation
                 locationItem.Latitude = geocoordinate.Latitude;
                 locationItem.Longitude = geocoordinate.Longitude;
                 locationItem.Altitude = geocoordinate.Altitude;
+                locationItem.City = _city ?? "";
+                locationItem.Country = _country ?? "";
                 locationItem.HorizontalAccuracy = geocoordinate.HorizontalAccuracy;
                 locationItem.VerticalAccuracy = geocoordinate.VerticalAccuracy;
                 locationItem.Speed = geocoordinate.Speed;
                 locationItem.Course = geocoordinate.Course;
                 locationItem.IsNewLocation = true;
                 locationItem.IsSelected = true;
-                locationItem.StoredTime = DateTime.Now;
             }
             else
             {
@@ -189,13 +195,14 @@ namespace WeatherInformation
                     Latitude = geocoordinate.Latitude,
                     Longitude = geocoordinate.Longitude,
                     Altitude = geocoordinate.Altitude,
+                    City = _city ?? "",
+                    Country = _country ?? "",
                     HorizontalAccuracy = geocoordinate.HorizontalAccuracy,
                     VerticalAccuracy = geocoordinate.VerticalAccuracy,
                     Speed = geocoordinate.Speed,
                     Course = geocoordinate.Course,
                     IsNewLocation = true,
                     IsSelected = true,
-                    StoredTime = DateTime.Now
                 };
 
                 // Add a location item to the local database.
index 1167e66..43f93c6 100644 (file)
@@ -244,25 +244,6 @@ namespace WeatherInformation.Model
             }
         }
 
-        private DateTime _storedTime;
-        [Column(CanBeNull = false)]
-        public DateTime StoredTime
-        {
-            get
-            {
-                return _storedTime;
-            }
-            set
-            {
-                if (_storedTime != value)
-                {
-                    NotifyPropertyChanging("StoredTime");
-                    _storedTime = value;
-                    NotifyPropertyChanged("StoredTime");
-                }
-            }
-        }
-
         #region INotifyPropertyChanged Members
 
         public event PropertyChangedEventHandler PropertyChanged;
index d855c90..dc5753e 100644 (file)
@@ -27,5 +27,26 @@ namespace WeatherInformation.Model.Services
         {
             return this._jsonParser.ParserWeatherData<ForecastWeather>(jsonData);
         }
+
+        public WeatherData WeatherDataParser(string JSONRemoteForecastWeather, string JSONRemoteCurrentWeather)
+        {
+            if (string.IsNullOrEmpty(JSONRemoteForecastWeather))
+            {
+                throw new ArgumentException("Missing argument", "JSONRemoteForecastWeather");
+            }
+            if (string.IsNullOrEmpty(JSONRemoteCurrentWeather))
+            {
+                throw new ArgumentException("Missing argument", "JSONRemoteCurrentWeather");
+            }
+
+            return new WeatherData
+            {
+                JSONRemoteCurrent = JSONRemoteCurrentWeather,
+                JSONRemoteForecast = JSONRemoteForecastWeather,
+                RemoteCurrent = GetCurrentWeather(JSONRemoteCurrentWeather),
+                RemoteForecast = GetForecastWeather(JSONRemoteForecastWeather),
+                WasThereRemoteError = false
+            };
+        }
     }
 }
index a9e6aa1..1248ddf 100644 (file)
@@ -3,12 +3,7 @@ using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.Globalization;
 using System.IO.IsolatedStorage;
-using System.Threading.Tasks;
-using System.Windows;
 using WeatherInformation.Model;
-using WeatherInformation.Model.ForecastWeatherParser;
-using WeatherInformation.Model.JsonDataParser;
-using WeatherInformation.Model.Services;
 using WeatherInformation.Resources;
 
 namespace WeatherInformation.ViewModels
@@ -27,13 +22,11 @@ namespace WeatherInformation.ViewModels
 
         // Settings
         private readonly IsolatedStorageSettings _settings;
-        private readonly ServiceParser _serviceParser;
 
         public MainViewModel()
         {
             this.ForecastItems = new ObservableCollection<ItemViewModel>();
             this.CurrentItems = new ObservableCollection<ItemViewModel>();
-            this._serviceParser = new ServiceParser(new JsonParser());
 
             // Get the _settings for this application.
             _settings = IsolatedStorageSettings.ApplicationSettings;