在wp7程序中,当程序功能越来越复杂时,性能问题是我们不得不考虑的一个问题。在聊天列表中,如果聊天项过多,而且项目UI组件足够复杂时,
我们不得不想尽办法让UI尽快加载。所以有一种可行的方案,就是像QQ聊天列表一样,从上至下,列表项逐一加载(加载完第一项,再加载第二项,再加载第三项,给用户尽快的UI响应,也不至于等待到显示所有的列表项。
在我们的例子中,我还给每个列表项显示的过程中加入了渐显动画,这样当列表项足够复杂时,也能表现出比较好的展示效果。
实现的基本原理:
实现的原理也不难,主要的思路是:
1.列表项原本只是一个简单的自定义ContentControl(Codewp7ItemContainer),等到合适的时机再加载他的content(Codewp7ListBoxItem);
2.使用一个管理类LoadService,对UI列表项的加载进行控制,当加载了一项后,再进行第二项的加载,再进行第三项的加载....。
3.给每一个实际的列表项的显示加入渐显动画。
开始看我们的实现吧:
ListItemObject: 列表的实际数据
public class ListItemObject { public string Title; public string Info; }
LoadService的队列控制实现
RoutedEventHandler itemLoaded;
List<UILoadAction> LoadItems = new List<UILoadAction>();
object LoadArrayLock = new object();
//当UILoad队列中 全部UI load成功,会回调这个函数
public event RoutedEventHandler LoadedComplete;
public void PushLoadAction(UILoadAction loadAction)
{
if (loadAction == null)
return;
lock (LoadArrayLock)
{
LoadItems.Add(loadAction);
}
if (LoadItems.Count <= 1)
{
PopLoadAction();
}
}
private void PopLoadAction()
{
if (LoadItems.Count <= 0)
{
// Log.d(TAG, "LoadedComplete!");
if (LoadedComplete != null)
{
LoadedComplete(null, null);
}
return;
}
mEle.Dispatcher.BeginInvoke(() =>
{
lock (LoadArrayLock)
{
UILoadAction action;
if (LoadItems.Count <= 0)
{
// Log.d(TAG, "LoadedComplete in BeginInvoke!");
if (LoadedComplete != null)
{
LoadedComplete(null, null);
}
return;
}
// Log.d(TAG, "LoadAction Array size:"+LoadItems.Count);
action = LoadItems[0];
action(item_Loaded);
// Log.d(TAG, "pop");
LoadItems.RemoveAt(0);
}
});
}
void item_Loaded(object sender, RoutedEventArgs e)
{
PopLoadAction();
}
对于每一项加入渐显动画
private Storyboard getLoadStoryBoard()
{
Storyboard ret;
// Prepare for scale animation
double from = 0;
double to = 1;
TimeSpan timespan = TimeSpan.FromSeconds(0.8);
IEasingFunction easingFunction = new ExponentialEase { EasingMode = EasingMode.EaseInOut };
ret = new Storyboard();
DoubleAnimation animationOpacity = new DoubleAnimation { From = from, To = to, Duration = timespan, EasingFunction = easingFunction };
Storyboard.SetTarget(animationOpacity, this);
Storyboard.SetTargetProperty(animationOpacity, new PropertyPath(UIElement.OpacityProperty));
ret.Children.Add(animationOpacity);
return ret;
}