一直以来Adapter的使用都仅仅是流于表面,仅仅知道要实现几个抽象的方法,把Adapter设置给某种listView,就能够非常好的工作起来。所谓理解仅仅是建立在主观的猜想上面,认为应该是这样,对,ok,就这样,恩, 明确了。可是其实却没有正真的懂它。这能够说Android的设计模式真的做得非常好,无需了解实现就能够非常好的运用,只是总感觉没有深入的追究还是少了点什么。那就看看它的一些细节吧。尤其来看看我一直疑惑的为什么调用notifyDataSetChanged  notifyDataSetInvalidated
就能够重绘View。

首先还是从我掌握的有限的线索開始,notifyDataSetChanged 方法是怎么实现的呢?

依据经验发现,差点儿我们用到的Adapter都是继承自BaseAdapter,借助eclipse 的Type Hierarchy View 也能够确认确实是这么回事,ok,那看看它的实现:

    /**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
} /**
* Notifies the attached observers that the underlying data is no longer valid
* or available. Once invoked this adapter is no longer valid and should
* not report further data set changes.
*/
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}

原来是个Observer的实现,这个倒是和我之前的猜想差点儿相同。

    public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}

看来能够挂非常多个Observer,继续看看onChanged实现发现时个abstract的,怎么办,究竟是谁呢?看来要找个详细的实现。看看比較熟悉的ListView

和比較熟悉的ListAdapter,在ListView的setAdapter里发现

            mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);

AdapterDataSetObserver的实如今AdapterView:

 class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;

        @Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount(); // Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
} @Override
public void onInvalidated() {
mDataChanged = true; if (AdapterView.this.getAdapter().hasStableIds()) {
// Remember the current state for the case where our hosting activity is being
// stopped and later restarted
mInstanceState = AdapterView.this.onSaveInstanceState();
} // Data is invalid so we should reset our state
mOldItemCount = mItemCount;
mItemCount = 0;
mSelectedPosition = INVALID_POSITION;
mSelectedRowId = INVALID_ROW_ID;
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false; checkFocus();
requestLayout();
} public void clearSavedState() {
mInstanceState = null;
}
}

ok,原来是这样来更新的,明确了。

总结起来看,全部的Adapter都是BaseAdapter的子类,全部的带Adapter的view都是AdapterView的子类。AbsListView也是AdapterView的子类。

在View和Adapter关联的时候会把view的Oberver注冊到adapter上,所以在adapter数据变化的时候。view就能够通过observer了解到,从而能够及时更新。

看来Adapter 模式的实现用了Oberver模式,隐隐约约还用到桥模式,不知道我的认识是不是正确呢。

Android深入研究Adapter重绘的更多相关文章

  1. Android视图状态及重绘流程分析,带你一步步深入了解View(三)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17045157 在前面一篇文章中,我带着大家一起从源码的层面上分析了视图的绘制流程, ...

  2. Android重绘ListView高度

    Android重绘ListView高度 经常会有这样需求,需要ListView默认将所有的条目显示出来,这就需要外层使用ScrollView,ScrollView里面放置一个重绘高度的ListView ...

  3. 《Android内核剖析》读书笔记 第13章 View工作原理【View重绘过程】

    计算视图大小的过程(Measure) 视图大小,准确的来说应该是指视图的布局大小:我们在layout.xml中为每个UI控件设置的layout_width/layout_height两个属性被用来设置 ...

  4. [Android FrameWork 6.0源码学习] View的重绘过程

    View绘制的三部曲,  测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,View需要重绘,都是发送请求给ViewRootImpl,然后他组织重绘在重绘的过程中 ...

  5. [Android FrameWork 6.0源码学习] View的重绘过程之WindowManager的addView方法

    博客首页:http://www.cnblogs.com/kezhuang/p/关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下<[Andr ...

  6. Android视图重绘,使用invalidate还是requestLayout

    概述 在我们在进行自定义View的相关开发中,当我们更改了当前View的状态,比如大小,位置等,我们需要重新刷新整个界面,保证显示最新的状态.在Android中,让当前的视图重绘有两种方式,inval ...

  7. Android View的重绘过程之WindowManager的addView方法

    博客首页:http://www.cnblogs.com/kezhuang/p/ 关于Activity的contentView的构建过程,我在我的博客中已经分析过了,不了解的可以去看一下 <[An ...

  8. Android View的重绘过程之Draw

    博客首页:http://www.cnblogs.com/kezhuang/p/ View绘制的三部曲,测量,布局,绘画现在我们分析绘画部分测量和布局 在前两篇文章中已经分析过了.不了解的可以去我的博客 ...

  9. Android View的重绘过程之Measure

    博客首页:http://www.cnblogs.com/kezhuang/p/ View绘制的三部曲,  测量,布局,绘画今天我们分析测量过程 view的测量是从ViewRootImpl发起的,Vie ...

随机推荐

  1. POJ 2240 Arbitrage(最短路 套汇)

    题意  给你n种币种之间的汇率关系  推断是否能形成套汇现象  即某币种多次换为其他币种再换回来结果比原来多 基础的最短路  仅仅是加号换为了乘号 #include<cstdio> #in ...

  2. jenkins集群加入Windows 2012 server作为slave

    必须安装.net framework 3.5, 參考: http://technet.microsoft.com/en-us/library/dn482071.aspx 不要在windows 2012 ...

  3. oracle 修改dbid和dbname

    一般这玩意没人修改,除非特殊情况,比如克隆数据库等等 步骤: 1.备份数据库 2.启动数据到mount状态 3.nid命令修改 (如果只是修改dbid,那么不需要dbname参数,需要更改dbname ...

  4. Enhancing the Application: Advanced JDBC Features(转)

    Enhancing the Application: Advanced JDBC Features This chapter describes additional functionality th ...

  5. Source Insight 光标变粗设置NotePad++光标设置

    为了更好的查看文档和代码,避免半天都找不到光标的情况,故做此说明 Source Insight 光标变粗 菜单中 Options --->Preferences --->Typing -- ...

  6. WinForm、wpf、silverlight三者关系

    最近在学C#.NET,基本语法学习的差不多了,接下来准备学习图形界面设计部分.但是我目前对于.NET的WinForm.wpf.silverlight这三者的关系弄的不是很清楚,一般书中很少介绍wpf和 ...

  7. IntelliJ IDEA 问题总结之中的一个 —— jar包、assets、maven、git

    因为工作须要,这几天開始弃用eclipse,换idea.用了几天,idea确实有些地方比較方便.可是麻烦也是不少.并且网上相应的资料并没有eclipse那么多,非常多都是自己琢磨解决的,所以想弄个帖子 ...

  8. 2014在百度之星资格赛的第二个问题Disk Schedule

    事实上,我认为它可以用来费用流问题.但光建地图上加班. ..不科学啊.. . 因副作用太大,否则,必然在.最后,想啊想,或者使用dp对.... 别想了一维dp... .我不知道我是怎么想.无论如何,这 ...

  9. 查看SQLSERVER内部数据页面的小插件Internals Viewer

    原文:查看SQLSERVER内部数据页面的小插件Internals Viewer 查看SQLSERVER内部数据页面的小插件Internals Viewer 感觉internals viewer这个名 ...

  10. 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)

    原文:乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) 作 ...