(七)手把手教你写天气预报程序:加入TombStone(墓碑机制)

上一节完成后,程序已经能够正常运行了。基本功能都完成了。是不是有种很不出的感觉呢。大家都应该听说过会这个墓碑机制了吧。因为window phone 是单任务系统,为后台程序留了5个坑。程序一旦进入后台,就休眠了。被埋在坑里了,就不再运行了。只有你按返回键才能从进入休眠的后台程序。不过,我觉得还有两个问题,第一个就是如果程序在后台,你从启动器启动程序,就是不是按返回键进入程序,那么程序就重新运行了。原来后台的数据就没了,这个是一个用户体验很不好的地方,比如我,就是不喜欢按返回键进入程序的,喜欢从启动器进入后台程序。第二个,就是只有5个坑,一旦你的程序进入后台之后,又有5个程序进入后台,那么你程序埋在坑里的尸体就被抛尸荒野了。再也不能从后台进入了,只能从启动器重新打开。。

那么,怎么解决呢,大家都是喜欢多任务运行的。我们就来模拟一把吧。

模拟之前,先要了解程序的生命周期,这些大家还是百度吧。现在只是简单说下涉及到声明周期要使用到的函数。在App.xaml.cs里面定义了那么4个函数,Launching,Activate,Deactivate,Closing。Launching在程序启动的时候执行。Deactivate在用户点击开始键或者其他导致程序进入后台的操作时候执行,Activate在用户按返回键进入程序的时候执行。closing不用多说,看名字就知道。在程序关闭的时候执行。

在我们这个程序,也就在设置页面的时候如果中断运行进入后台的话才需要恢复,所以相对简单些。我的方案是:定义了两个变量,一个是保存当前所在页面的CurrentPage(保存到PhoneApplicationService),一个是保存是否中断到后台的Recovery。.在Deactivate函数里面保存需要的相关值和上面两个变量到Isolatedstorage。并且在Launching的时候把原来Deactivate保存的值取出来。然后再PageLoad 的时候判断是否是中断恢复。是的话就导航到相关页面,然后恢复界面值。恢复完成,Recovery设置为false,并且保存到Isolatedstorage。

 

在写代码之前,还要了解的是每个Page里面都有两个事件,OnNavigatedFrom和OnNavigatedTo,前者就是离开页面的时候执行,后者是进入页面的时候执行。重载这两个事件就能用了。

 

下面先修改App.xaml.cs的代码:(代码中可能没添加命名空间,自己加吧,很简单)

IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings;

        private void Application_Launching(object sender, LaunchingEventArgs e)

        {



            //如果数据库不存在则创建一个数据库,并且存入相关数据



            CreatDB();



            #region 把Deactivate保存的相关数据取出来

            string temp;

            if (iss.TryGetValue("LastPage", out temp))

            {

                PhoneApplicationService.Current.State["CurrentPage"] = temp;

            }

            int index;

            if (iss.TryGetValue("cityIndex", out index))

            {

                PhoneApplicationService.Current.State["cityIndex"] = index;

            }

            if (iss.TryGetValue("provIndex", out index))

            {

                PhoneApplicationService.Current.State["provIndex"] = index;

            } 

            #endregion

        }





        private void Application_Deactivated(object sender, DeactivatedEventArgs e)

        {

            #region 程序即将进入后台,保存中断情况的相关数据

            iss["Recovery"] = true;

            if (PhoneApplicationService.Current.State.ContainsKey("cityIndex"))

            {

                iss["cityIndex"] = PhoneApplicationService.Current.State["cityIndex"];

            }

            if (PhoneApplicationService.Current.State.ContainsKey("provIndex"))

            {

                iss["provIndex"] = PhoneApplicationService.Current.State["provIndex"];

            }

            if (PhoneApplicationService.Current.State.ContainsKey("CurrentPage"))

            {

                iss["LastPage"] = PhoneApplicationService.Current.State["CurrentPage"];

            } 

            #endregion



        }



        private void Application_Closing(object sender, ClosingEventArgs e)

        {

            //退出,

            iss["Recovery"] = false;

        }

 


下面修改MainPage的代码:(PageLoad修改如下)

 

 

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

        {

            #region 判断是否是中断进入

            IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings;

            bool recov;

            if (iss.TryGetValue("Recovery", out recov))

            {

                if (recov)

                {

                    if (PhoneApplicationService.Current.State.ContainsKey("CurrentPage"))

                    {

                        string temp = Convert.ToString(PhoneApplicationService.Current.State["CurrentPage"]);

                        if (!temp.Equals("MainPage.xaml") && temp.Length > 0)

                        {

                            NavigationService.Navigate(new Uri("/WeatherForecast;component/" + temp, UriKind.Relative));

                        }

                        else

                        {

                            iss["Recovery"] = false;

                        }

                    }

                }

                else

                    PhoneApplicationService.Current.State["CurrentPage"] = "MainPage.xaml";

            }

            else

                PhoneApplicationService.Current.State["CurrentPage"] = "MainPage.xaml";

            #endregion

            UpdateWeather();

        }

 


 

我们主要做的是SetPage的中断进入后台的处理,所以,要重载OnNavigatedFrom事件来保存两个Listpicker的SelectedIndex。而且,要在PageLoad的时候判断是否是中断返回,如果是那么就恢复。不是就常规绑定。下面是修改或者增加的代码:

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

        {

            #region 判定是否是中断退出后进入,是就恢复数据

            IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings;

            bool recov;

            if (iss.TryGetValue("Recovery", out recov))

            {

                if (recov)

                {

                    if (PhoneApplicationService.Current.State.ContainsKey("CurrentPage"))

                    {

                        string temp = Convert.ToString(PhoneApplicationService.Current.State["CurrentPage"]);

                        if (temp.Equals("SetPage.xaml"))

                        {

                            int provIndex = 0;

                            int cityIndex = 0;

                            if (PhoneApplicationService.Current.State.ContainsKey("provIndex"))

                            {

                                provIndex = Convert.ToInt32(PhoneApplicationService.Current.State["provIndex"]);

                            }

                            if (PhoneApplicationService.Current.State.ContainsKey("cityIndex"))

                            {

                                cityIndex = Convert.ToInt32(PhoneApplicationService.Current.State["cityIndex"]);

                            }

                            RecovListPickerItems(provIndex, cityIndex);//恢复数据

                            iss["Recovery"] = false;//设置为已经恢复



                        }

                        else

                            ProvLpDataBind();

                    }

                    else

                        ProvLpDataBind();

                }

                else

                    ProvLpDataBind();

            }

            else

                ProvLpDataBind();

            #endregion

            PhoneApplicationService.Current.State["CurrentPage"] = "SetPage.xaml";

        }



        /// <summary>

        /// 恢复数据的时候绑定city的ItemSource,并且绑定两个ListPicker的当前选项

        /// </summary>

        /// <param name="provIndex"></param>

        /// <param name="cityIndex"></param>

        void RecovListPickerItems(int provIndex, int cityIndex)

        {

            provincelp.ItemsSource = prov;

            if (provIndex < 0 || provIndex >= prov.Length)

            {

                provIndex = 0;

            }

            provincelp.SelectedIndex = provIndex;

            List<String> l = cityDataBind(prov[provIndex]);

            if (cityIndex < 0 || cityIndex >= l.Count())

            {

                cityIndex = 0;

            }

            citylp.SelectedIndex = cityIndex;



        }



        /// <summary>

        /// 离开页面保存当前两个ListPicker的selectedIndex

        /// </summary>

        /// <param name="e"></param>

        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)

        {

            base.OnNavigatedFrom(e);

            PhoneApplicationService.Current.State["provIndex"] = provincelp.SelectedIndex;

            PhoneApplicationService.Current.State["cityIndex"] = citylp.SelectedIndex;

        }

 

这样,多任务模拟就完成了。无论是从返回键返回程序还是从启动器启动返回程序。都行。不过,如果要做的页面太多,控件太多还真是很麻烦的。

 

PS:这里的断点调试技巧:由于要测试从启动器恢复程序,但是编译器调试的时候,一旦点击开始按钮进入后台,然后从启动器进入程序,编译器调试就退出了。因为原来的程序已经终结了。其实我们可以这样。点击开始按钮进入后台后,回到编译器点击终止调试,然后再次启动启动。那么这样的话就可以到需要调试的断点了。毕竟这里的判断还是很多,容易出错。其实这个是利用的是Isolatedstorage的特点,模拟器不关闭这个Isolatedstorage的数据是不会丢失的。

 

这节工程下载:chapter7

 

继续学习:<WP7>(八)手把手教你写天气预报程序:自定义about消息框和程序收尾

你可能感兴趣的:(天气预报)