当前位置:  编程技术>移动开发
本页文章导读:
    ▪为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?      在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,我希望能够通过调用 mAdapter.notifyDataSet.........
    ▪MVVM中间接使用事件(命令)      在使用MVVM模式时, 按照模式的规则是尽量不直接使用事件. 所以对于以前一直使用事件模式的同行来说确实有点头疼. 还好微软给我们提供了几种间接使用事件(命令)的方法, 下面我就来看看这.........
    ▪通过UIImage显示网络图片      显示图片也有点绕,代码如下://生成一个NSURLnextDraw.imageUrl = [NSURLURLWithString:@"ddddd.png" relativeToURL:[NSURLURLWithString:@"http://ggggggggg.com/"]];//获取UIImage控件,可以是IBOutletUIImageView * imageNe.........

[1]为什么调用 FragmentPagerAdapter.notifyDataSetChanged() 并不能更新其 Fragment?
    来源:    发布时间: 2013-11-15
在一个 Android 应用中,我使用 FragmentPagerAdapter 来处理多 Fragment 页面的横向滑动。不过我碰到了一个问题,即当 Fragment 对应的数据集发生改变时,我希望能够通过调用 mAdapter.notifyDataSetChanged() 来触发 Fragment 页面使用新的数据调整或重新生成其内容,可是当我调用 notifyDataSetChanged() 后,发现什么都没发生。
 
搜索之后发现不止我一个人碰到这个问题,大家给出的解决办法五花八门,有些确实解决了问题,但是我总感觉问题没搞清楚。于是我决定搞明白这个问题到底是怎么回事,以及正确的用法到底如何。要搞明白这个问题,仅仅阅读文档并不足够,还需要阅读相关几个类的相关方法的实现,搞懂其设计意图。下面就是通过阅读源代码搞明白的内容。
 
 
【ViewPager】


ViewPager 如其名所述,是负责翻页的一个 View。准确说是一个 ViewGroup,包含多个 View 页,在手指横向滑动屏幕时,其负责对 View 进行切换。为了生成这些 View 页,需要提供一个 PagerAdapter 来进行和数据绑定以及生成最终的 View 页。
 
  • 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() 来生成新的对象。
 
【PagerAdapter】

 

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 的操作。
 
【FragmentPagerAdapter】
 
FragmentPagerAdapter 继承自 PagerAdapter。相比通用的 PagerAdapter,该类更专注于每一页均为 Fragment 的情况。如文档所述,该类内的每一个生成的 Fragment 都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种;如果需要处理有很多页,并且数据动态性较大、占用内存较多的情况,应该使用
    
[2]MVVM中间接使用事件(命令)
    来源:    发布时间: 2013-11-15

在使用MVVM模式时, 按照模式的规则是尽量不直接使用事件. 所以对于以前一直使用事件模式的同行来说确实有点头疼. 还好微软给我们提供了几种间接使用事件(命令)的方法, 下面我就来看看这几种方法:

ICommand

ICommand定义了一个接口, 使用它可以轻松的将实现ICommand的接口的命令绑定到包含命令(Command)的控件上(例如Button.Command), 在.net framework库中实现的这个接口的类不是很多, 我所知道的两个: RoutedCommand 和 RoutedUICommand, 而且这两个使用起来比较麻烦, 在这里我就不谈了, 有兴趣的同行可以研究一下. 那么, 除了上述的两个类以外还有自定义类实现ICommand和Prism的DelegateCommand. 我们先看一下自定义的;

1. 自定义命令

MyCommand是实现ICommand接口的一个类. 在Execute方法中我们调用传入的Action(Action包含所要实现的功能的方法), IsEnabledExecute是自定义的一个bool类型, 通过设置该值可以启用(禁用)ICommand所绑定到的控件的启用禁用状态.

1 public class MyCommand : 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后我们就可以使用了, 代码如下:

1 public class MvvmEventViewModel
2 {
3
4 public MvvmEventViewModel()
5
6 {
7
8 /*自定义命令*/
9
10 MyCommandInstance =
    
[3]通过UIImage显示网络图片
    来源:    发布时间: 2013-11-15

显示图片也有点绕,代码如下:

//生成一个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];

 

如果要异步还有其他方法了。

本文链接


    
最新技术文章:
 




特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3