- setAdapter()
- ViewPager 通过 setAdapter() 来建立与 PagerAdapter 的联系。这个联系是双向的,一方面,ViewPager 会拥有 PagerAdapter 对象,从而可以在需要时调用 PagerAdapter 的方法;另一方面,ViewPager 会在 setAdapter() 中调用 PagerAdapter 的 registerDataSetObserver() 方法,注册一个自己生成的 PagerObserver 对象,从而在 PagerAdapter 有所需要时(如 notifyDataSetChanged() 或 notifyDataSetInvalidated() 时),可以调用 Observer 的 onChanged() 或 onInvalidated() 方法,从而实现 PagerAdapter 向 ViewPager 方向发送信息。
- dataSetChanged()
- 在 PagerObserver.onChanged(),以及 PagerObserver.onInvalide() 中被调用。因此当 PagerAdapter.notifyDataSetChanged() 被触发时,ViewPager.dataSetChanged() 也可以被触发。该函数将使用 getItemPosition() 的返回值来进行判断,如果为 POSITION_UNCHANGED,则什么都不做;如果为 POSITION_NONE,则调用 PagerAdapter.destroyItem() 来去掉该对象,并设置为需要刷新 (needPopulate = true) 以便触发 PagerAdapter.instantiateItem() 来生成新的对象。
PageAdapter 是 ViewPager 的支持者,ViewPager 将调用它来取得所需显示的页,而 PageAdapter 也会在数据变化时,通知 ViewPager。这个类也是FragmentPagerAdapter 以及 FragmentStatePagerAdapter 的基类。如果继承自该类,至少需要实现 instantiateItem(), destroyItem(), getCount() 以及 isViewFromObject()。
- getItemPosition()
- 该函数用以返回给定对象的位置,给定对象是由 instantiateItem() 的返回值。
- 在 ViewPager.dataSetChanged() 中将对该函数的返回值进行判断,以决定是否最终触发 PagerAdapter.instantiateItem() 函数。
- 在 PagerAdapter 中的实现是直接传回 POSITION_UNCHANGED。如果该函数不被重载,则会一直返回 POSITION_UNCHANGED,从而导致 ViewPager.dataSetChanged() 被调用时,认为不必触发 PagerAdapter.instantiateItem()。很多人因为没有重载该函数,而导致调用
PagerAdapter.notifyDataSetChanged() 后,什么都没有发生。
- instantiateItem()
- 在每次 ViewPager 需要一个用以显示的 Object 的时候,该函数都会被 ViewPager.addNewItem() 调用。
- notifyDataSetChanged()
- 在数据集发生变化的时候,一般 Activity 会调用 PagerAdapter.notifyDataSetChanged(),以通知 PagerAdapter,而 PagerAdapter 则会通知在自己这里注册过的所有 DataSetObserver。其中之一就是在 ViewPager.setAdapter() 中注册过的 PageObserver。PageObserver 则进而调用 ViewPager.dataSetChanged(),从而导致 ViewPager 开始触发更新其内含 View 的操作。
在使用MVVM模式时, 按照模式的规则是尽量不直接使用事件. 所以对于以前一直使用事件模式的同行来说确实有点头疼. 还好微软给我们提供了几种间接使用事件(命令)的方法, 下面我就来看看这几种方法:
ICommand
ICommand定义了一个接口, 使用它可以轻松的将实现ICommand的接口的命令绑定到包含命令(Command)的控件上(例如Button.Command), 在.net framework库中实现的这个接口的类不是很多, 我所知道的两个: RoutedCommand 和 RoutedUICommand, 而且这两个使用起来比较麻烦, 在这里我就不谈了, 有兴趣的同行可以研究一下. 那么, 除了上述的两个类以外还有自定义类实现ICommand和Prism的DelegateCommand. 我们先看一下自定义的;
1. 自定义命令
MyCommand是实现ICommand接口的一个类. 在Execute方法中我们调用传入的Action(Action包含所要实现的功能的方法), IsEnabledExecute是自定义的一个bool类型, 通过设置该值可以启用(禁用)ICommand所绑定到的控件的启用禁用状态.
2
3 {
4
5 public MyCommand(Action<object> action)
6
7 {
8
9 if (action == null) throw new ArgumentNullException();
10
11 _action = action;
12
13 }
14
15
16
17 private readonly Action<object> _action;
18
19
20
21 private bool _isEnabledExecute = true; //默认为启用状态
22
23 public bool IsEnabledExecute
24
25 {
26
27 get { return _isEnabledExecute; }
28
29 set
30
31 {
32
33 if (_isEnabledExecute != value)
34
35 {
36
37 _isEnabledExecute = value;
38
39 if (CanExecuteChanged != null)
40
41 {
42
43 CanExecuteChanged(this, new EventArgs());
44
45 }
46
47 }
48
49 }
50
51 }
52
53
54
55 #region ICommand 接口
56
57 public event EventHandler CanExecuteChanged;
58
59
60
61 public bool CanExecute(object parameter)
62
63 {
64
65 return _isEnabledExecute;
66
67 }
68
69
70
71 public void Execute(object parameter)
72
73 {
74
75 _action(parameter);
76
77 }
78
79 #endregion
80
81 }
定义好MyCommand后我们就可以使用了, 代码如下:
2 {
3
4 public MvvmEventViewModel()
5
6 {
7
8 /*自定义命令*/
9
10 MyCommandInstance =
显示图片也有点绕,代码如下:
//生成一个NSURL
nextDraw.imageUrl = [NSURLURLWithString:@"ddddd.png" relativeToURL:[NSURLURLWithString:@"http://ggggggggg.com/"]];
//获取UIImage控件,可以是IBOutlet
UIImageView * imageNextDraw = (UIImageView *)[cell viewWithTag:103];
//同步下载到NSData
NSData* data = [NSData dataWithContentsOfURL:nextDraw.imageUrl];
//显示图片
imageNextDraw.image = [UIImage imageWithData:data];
如果要异步还有其他方法了。
本文链接