<WP7>(七)手把手教你写天气预报程序:加入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消息框和程序收尾

posted on 2012-04-30 16:24  fengyun1989  阅读(846)  评论(3编辑  收藏  举报