您的位置:首页 > 其它

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

2012-04-30 16:24 531 查看
上一节完成后,程序已经能够正常运行了。基本功能都完成了。是不是有种很不出的感觉呢。大家都应该听说过会这个墓碑机制了吧。因为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消息框和程序收尾
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐