大家好,我是你的好朋友思创斯。今天说一说android anr分析_安卓odex,希望您对编程的造诣更进一步.
目录
gallery2主要功能是实现android系统本地存储以及网络存储中的媒体(图片&视频)资源的浏览,媒体信息,显示和更多操作(删除、分享、选择、缩放、编辑等)。
gallery2界面的生成和普通的应用程序不同,普通应用程序一般就一个界面对应一个activity,搭配布局xml或代码来实现界面的显示,而gallery2没有用到android的ui系统,而是通过opengl画出来,只用到了一个acitivity.、
android4.x后的gallery2的主要组成有:
①albumsetpage 所有专辑界面,点击gallery图标后进入图库所显示的第一个页面;
②albumpage 单个专辑界面,albumsetpage的一个子集,显示该专辑内的所有图片,专辑通过文件夹来区分;
③photopage 单张图片界面,可用通过albumpage进入,也可以通过外部调用浏览单张图片。



基本数据
gallery2中描述单个媒体对象的数据结构图如下:

gallery2中描述一组媒体对象的数据结构图如下:

mediaobject 数据渲染的最小单位,它包含丰富的衍生类。mediaobject定义了媒体数据最基本的信息,如supportedoperations,supportedoperations定义这个媒体文件支持的操作,如是否可以delete/share/rotate等。定义了最基本的path路径,用于表示媒体对象的存储地址;
mediaitem mediaobject的衍生类,mediaobject的封装,是单个媒体的抽象,代表一张图片或者一个视频。在此抽象类中,定义getmimetype()/getwitdh()/getheight()等抽象方法。;
localmediaitem mediaitem的衍生类,对本地mediaitem的抽象,代表一张本地图片或者一个本地视频。在此抽象类中,添加定义了bucketid/datadirty; bucketid由文件夹的绝对路径的hashcode来表示,代表一个专辑,是专辑的索引。通过galleryutils的getbucketid可以获得传入路径的bucketid。
localimage localmediaitem的子类,表示一个本地存储的图片。内部定义了一个item_path=”/local/image/item”。首先localimage的初始化有两种,一种是通过直接传入cursor对象来初始化这个image对象,另外一种是通过传入id的形式来查询外部存储的数据库,得到cursor,进而初始化这个image对象。
mediaset 和mediaitem一样是mediaobject的衍生类,是一个类目录的数据结构,是一组媒体文件的抽象。它提供的主要基础接口有getmediaitemcount, getmediaitem, getsubmediasetcount, getsubmediaset, gettotalmediaitemcount. 还定义了getcovermediaitem来获得一组图片或视频的封面。
localalbumset 继承于mediaset,是所有图片和视频专辑的集合。其内部定义了三个path,分别是path_all,path_image,path_video.其内部定义了malbums用来保存专辑列表。localalbumset是albumsetpage的单位。
localalbum 继承于mediaset,代表一个bucket(目录)下的所有的media items。提供mediaitem的查询,删除等操作。localalbum是albumpage的单位。

数据源
gallery2中引入数据源的概念,由datamanager负责管理,目的是在不同的显示界面,能通过datamanager获得一个合适的数据源来初始化自己的数据。gallery2中主要定义的数据源有combosource(组合源), picasasource(picasa源),localsource(本地源), clustersource(簇源), urisource(url源),filtersource(过滤源)。这些数据源有一个共同的基类mediasource, mediasource是对数据源的抽象,它里面主要定义了数据源的基本组成,如定义了数据源的唯一标识prefix, prefix后面会讲到。
datamanager数据管理
在详细分析数据源的组成结构之前,首先来分析下datamanager。datamanager是用来管理整个系统中的所有media sets(集合)和media item。datamanager在gallery application启动时就创建并且初始化,可以通过galleryappimpl的getdatamanager方法来获得datamanager实例,datamanager的初始化做了以下事情:
addsource(new localsource(mapplication));
addsource(new picasasource(mapplication));
addsource(new combosource(mapplication));
addsource(new clustersource(mapplication));
addsource(new filtersource(mapplication));
addsource(new urisource(mapplication));
可以看出,datamanager实例化的同时也创建了所有数据源实例,并把它们加入自身维护的一个sourcemap中,提供存取操作。sourcemap中保存的索引是上面讲到的prefix。prefix是数据源的唯一标识,在数据源的构造方法中赋值。如localsource的prefix为”local”, combosource的prefix为”combo”。
void addsource(mediasource source) {
if (source == null) return;
msourcemap.put(source.getprefix(), source);
}
datamanager不仅提供了丰富的数据操作接口,同时定义了一组代表数据集合的path:
top_set_path = “/combo/{/local/all,/picasa/all}”; //表示用户能看到的最顶端的数据集合
top_image_set_path = “/combo/{/local/image,/picasa/image}”; //表示用户能看到的最顶端的图片数据集合
top_video_set_path = “/combo/{/local/video,/picasa/video}”; //表示用户能看到的最顶端的视频数据集合
top_local_set_path = “/local/all”; //表示用户能看到的最顶端的本地数据集合
top_local_image_set_path = “/local/image”; //表示用户能看到的最顶端的本地图片集合
top_local_video_set_path = “/local/video”; //表示用户能看到的最顶端的本地视频集合
数据范围的比较如下:
top_set_path > string top_image_set_path = top_video_set_path > top_local_set_path > top_local_image_set_path = top_local_video_set_path
//插入一张datamanager的一张类结构图

localsource本地数据源
localsource表示本地存储器中的所有media数据源,负责管理local media数据集。从它的createmediaobject方法(继承于mediasource)可以看出,它可以根据传入的path路径,创建出localalbumset,localalbum,localmergealbum,localimage,localvideo所有本地媒体数据相关的数据集合以及单个媒体文件。
public mediaobject createmediaobject(path path) {
galleryapp app = mapplication;
switch (mmatcher.match(path)) {
case local_all_albumset:
case local_image_albumset:
case local_video_albumset:
return new localalbumset(path, mapplication);
case local_image_album:
return new localalbum(path, app, mmatcher.getintvar(0), true);
case local_video_album:
return new localalbum(path, app, mmatcher.getintvar(0), false);
case local_image_item:
return new localimage(path, mapplication, mmatcher.getintvar(0));
case local_video_item:
return new localvideo(path, mapplication, mmatcher.getintvar(0));
default:
throw new runtimeexception(“bad path: ” path);
}
}
那么localsource是怎样根据传入的path来生成albumset,还是album呢?首先我们先来看看localsource的构造方法:
public localsource(galleryapp context) {
super(“local”);
mapplication = context;
mmatcher = new pathmatcher();
mmatcher.add(“/local/image”, local_image_albumset);
mmatcher.add(“/local/video”, local_video_albumset);
mmatcher.add(“/local/all”, local_all_albumset);
mmatcher.add(“/local/image/*”, local_image_album);
mmatcher.add(“/local/video/*”, local_video_album);
mmatcher.add(“/local/all/*”, local_all_album);
mmatcher.add(“/local/image/item/*”, local_image_item);
mmatcher.add(“/local/video/item/*”, local_video_item);
}
localsource的构造方法中实例化了pathmatcher,并将所有代表local资源相关的path及其类型添加到pathmatcher实例中。这里pathmatcher的作用是维护一个树结构,用于保存path以及匹配path类型。pathmatcher类内部定义一个node(节点),代表树的一个节点。node由hashmap以及一个整型kind组成,其中hashmap用来保存路径子段和node的映射,而整型kind用来保存该节点的类型,如(local_image_albumset/local_video_albumset)等。先来说一下pathmatcher的实现过程,在pathmatcher的构造方法中,首先创建了一个名为root的树的根节点,这个root的根节点作为match操作的入口。另外,patchmatcher通过add方法,先将传入的path路径以”/”为分割符创建segments数组,然后通过segments数组的元素构造树结构,并给最后一个节点的kind类型赋值,表示从根节点到该节点生成的path代表哪个类型的媒体结构。

匹配的过程如下:
path = “/local/image/item/10001”
序列为:
[local][image][item][10001]
二叉树查询:
kind=local_image_item, 生成localimage, id=10001
media数据的加载过程
我们从点击gallery2图标进入图片专辑页面这个过程为例,描述一下local数据的加载过程。
首先点击图库图标进入galleryactivity(旧版本或者命名为gallery),这个activity是整个图库程序的入口,非外部action_view调用下,调用startdefaultpage启动albumsetpage(就是我们打开gallery2后见到的第一个专辑页面),这时传入给albumsetpage一个名为media-path的参数,media-path值为”/combo/{/local/all,/picasa/all}”,这个是一个combo类型的path,表示需要显示local以及picasa两个组合的所有的媒体文件,具体的解析步骤如下:
(1)在albumsetpage的initializedata方法取出media-path,mediapath = /combo/{/local/all,/picasa/all}
(2)albumsetpage通过datamanager实例解析出由两个segments组成的url
segments[0]:combo
segments[1]:{/local/all,/picasa/all}
(3)第二部解析出来path的prefix(前缀)是bombo,datamanager通过这个prefix取得对应的数据源,这里获得的数据源是combosource
(4)datamanager调用combosource的createmediaobject方法来初始化comboalbumset实例返回到albumsetpage,与此同时,在构造comboalbumset时,继续分拆大括号里的/local/all和/picasa/all,生成localsource实例和emptysource实例。
(4.1)分拆/local/all,创建localsource数据源,生成localalbumset实例。
segments[0]:local
segments[1]:all
current path=/local/all prefix=local
(4.2)分拆/picasa/all,创建picasasource数据源,生成emptyalbumset实例
segments[0]:picasa
segments[1]:all
current path=/picasa/all prefix=picasa
(1)~(4)是albumsetpage中initializedata调用获取mmediaset所做的事情,这里返回的mmediaset实例就是指向一个由combosource数据源创建的comboalbumset实例,后面这个mmediaset的所有实现都可以在comboalbumset中找到。获得mmediaset后,initializedata里继续做的事情有,用mmediaset初始化mselectionmanager来管理这个界面的所有选择操作;用mmediaset初始化albumsetdataloader实例,作为数据适配器,数据取自mmediaset,这里生成的实例名叫malbumsetdataadapter,也很形象,数据源和适配器都准备完毕后,malbumsetview通过setmode方法将适配器传入渲染器中。

gallery2页面结构
android 4.x的gallery2主要由albumsetpage, albumpage, photopage三个页面组成,它们都继承自activitystate。activitystate会在下面描述,实际上可以把activitystate看作是gallery2三个页面中的其中一个activity状态,也可以理解成当前activity以哪种界面显示。 一般我们见到的程序窗口,大多是用actiivty来实现的,而gallery2中,实际上只有一个activity,叫abstractgalleryactivity,gallery2通过activitystate和statemanager来实现三个页面在同一个activity中显示和切换。
在讲三个主要界面之前,先来了解一下gallery2这个特殊的显示结构。
activitystate
gallery2中定义了activitystate这样一个抽象类,表示一个页面的状态,或者可以理解成在galelry2中,这就是一个界面。每一个子页面(如albumsetpage)都是activitystate的衍生类。
activitystate有一整套类似activity一样的生命周期,整个生命周期全部由statemanager来管理。
activitystate的结构和activity十分的类似,可以说是一个精简的activity。和startactivity来启动一个activity不同,activitystate通过statemanager的startstate方法来开启,整个生命周期的管理由statemanager来管理。

① activitystate和activity的类结构对比
statemanager
statemanager的作用类似于activitymanager,是每个子页面(activitystate)的管理类,负责子页面的切换,命令的执行,页面的刷新显示等职能,是activtystate的调度器。gallery将所有页面操作命令交给statemanager来执行,statemanager再将命令分发给当前的子页面执行。
statemanger可以通过abstractgalleryactivity的getstatemanager方法获得。statemanager中包含一个堆栈mstack,用于保存activtystate,和activity一样的实现方式,子页面先进后出,当切换到新的子页面时,当前页面压入堆栈中。当用户按back返回时,当前页面出栈并销毁,前一个子页面做为当前显示界面。
statemanager是一个桥梁,将真正的actiivty(galleryactivity)和activitystate状态关联起来。当启动gallery2时,首先执行galleryactivity的oncreate方法,然后调用statemanager的startstate方法加载albumsetpage,statemanager在startstate方法中,首先
会判断当前堆栈栈顶是否为空,由于albumsetpage是第一页面,此时堆栈为空,因此albumsetpage会被压入堆栈中,并在栈顶显示。在将albumsetpage压入栈后,会依次执行albumsetpage的oncreate和onresume方法。这样一来给人的感觉就是,我启动了albumsetpage,同样会执行oncreate和onresume方法,从actiivty到activitystate状态的同步是通过statemanager来传递的(图9)。
同时satemanager也是activitystate之间切换的桥梁,举个例子:从albumsetpage进入albumpage的过程中,在albumsetpage中通过调用satemanager的startstateforresult(类似于startactivityforresult,含返回值)方法切换到albumpage,此时albumsetpage会被压入堆栈,执行onpause方法。并建立albumpage并将其进栈,执行oncreate, onresume方法,最终albumpage在栈顶显示。当用户执行back事件后跳回albumsetpage页面,albumpage出栈并执行onstop和ondestory方法。
activity到activitystate状态的传递过程
galleryappimpl
galleryappimpl继承于application并实现了galleryapp接口,gallery2应用程序启动后首先执行galleryappimpl,galleryapp接口抽象了gallery2作为图库所要实现的最基本操作,例如getdatamanager获取数据管理器加载图片视频数据,getimagecacheservice获取图片缓存服务,getdownloadcache获取下载缓存,getthreadpool获取线程池等。
galleryappimpl的oncreate方法主要执行galleryutils工具类的initialize初始化方法来获得手机屏幕的分辨率大小等信息。
abstractgalleryactivity
abstractgalleryacitivty是gallery2最重要的一个activity,gallery2只有一个actiivty用于显示,它就是abstractgalleryactivity,它的派生类galleryactivity是程序的主入口。abstractgalleryactivity实现了gallerycontext接口,包括statemanager的初始化,在statemanager的初始化中传入abstractgalleryactiivty的对象引用,这样就statemanager以及它的所有子类都可以通过该引用调用abstractgalleryactivity提供的方法。
同时abstractgalleryactivity提供很多实用方法,如调用getdatamanager得到datamanager实例,通过getglroot方法获得glrootview,通过getgalleryactionbar方法获得galleryactionbar等。
galleryactivity
galleryactivity是abstractgalleryactivity的衍生类,是gallery2程序的主入口,在oncreate方法中initializebyintent来判断调用的方式,调用方式包括action_get_content,action_pick,action_view和default,根据不同的action执行正确的gallery调用。如在mms中调用gallery2添加图片资源,mms会发出action_pick广播进入gallery2选择图片。
如果action不属于以上(直接点击程序图标进入),galleryactivity执行startdefaultpage方法,该方法调用statemanager的startstate方法进入albumsetpage,并传入的key_media_path值为include_all,表示在albumsetpage中查看所有media。
albumsetpage数据加载和渲染过程分析
albumsetpage是我们进入gallery2后的第一个页面,作用是显示所有相册专辑。其结构主要由一个slotview和slot组成(如下图)。一个slot代表一个相册专辑。slot中包含的内容有:一张封面图片(一般是相册中首张图片资源),相册标题,相册大小等,如果这是一个特殊的相册,例如是一个保存camera拍照后的相册,在相册封面上还会有camera图标表示。

albumsetpage
第一步 initializeviews,目的是初始化 slotview 以及其渲染器 malbumsetview。 首先初始化 mselectionmanager,用于管理选择事件;
初始化 mconfig 获得有关 albumsetpage 的运行参数,包括 slot 的组成元素的颜色,初始化每个 slot 在 slotview 中的大小,间隔等 参数;
初始化 albumsetslotrenderer,slotview 的渲染器,实例名为 malbumsetview;
根据 mconfig 和 albumsetslotrenderer 初始化 mslotview,并给 mslotview 注册事件监听; 初始化 mactionmodehandler 处理 actionbar 事件;
最终将 slotview 添加到 rootpane 中;

第二步 initializedata,目的是实例化数据适配器,并为渲染器提供数据接口。
获得 galleryactivity 传过来的 mediapath,并通过 datamanager 的 getmediaset 方法获得对应的数据源,由于传过来的 mediapath 为
/combo/{/local/all,/picasa/all},因此得到的是一个 combosource 数据源,此数据源另外包含一个 localsource 和 emptysource,后面这 个 mmediaset 所有的实现都可以在 comboalbumset 中找到;
根据获得的数据源(mediaset)来实例化名为 malbumsetdataadapter 的 albumsetdataloader 对象,作为数据适配器。数据源和适配 器都准备完毕后,调用 setmode 方法将数据适配器添加到 slotview 的渲染器 malbumsetview 中;
第三步 调用数据适配器加载媒体数据,为后面渲染提供数据支持。
albumsetpage 的 oncreate 方法执行完后,在随后执行 onresume 方法中,首先调用数据适配器(albumsetdataloader)的 resume 方 法开始执行数据加载操作。albumsetdataloader 开启一个 reloadtask 执行数据源 reload 工作。通过层层的 reload,并调用 buckethelper 查询 mediaprovider 数据库,获得专辑数据并返回。
reloadtask 的主要功能是循环调用数据源的 reload 方法,进而更新获得专辑数据,一旦获得专辑数量变化后,通过监听器回调的 方式通知 slotview,告知专辑数,创建相应数量的 slot,这也是我们平时看到的专辑。
数据加载流程图
第四步 获得 albumset 数据后,渲染器开始渲染 slotview
数据适配器 albumsetdataloader 中的 reloadtask 执行完后,发送 msg_load_finish 广播通知到 albumsetpage 更新界面,并完成
slotview 渲染前的准备工作,流程如下:

线程池的基本思想是一种对象池的思想,系统开辟一块内存空间,里面存放着众多(未死亡)的线程,池中线程的执行调度由池 管理器来处理。当有线程任务时,池管理器会从池中取一个,执行完成后线程对象归池,这样就可以避免反复创建线程对象所带来的 性能开销了,从而节省了系统资源。
用线程池来管理的好处是,可以保证系统稳定性,适用于有大量线程,高工作量的情景下使用,假如现在我们有 2000 张图片资源
加载并显示,如果创建 2000 个线程区加载执行,系统肯定会死掉,线程池就可以避免这个问题,方案是可以用 5 个线程轮流执行,5 个为一组,执行完成后不直接回收,而是等待下次执行,这样对系统的开销就可以大大减少。
executor 是 java 工具类,执行提交给它的 runnable 任务。该接口提供了一种基于任务运行机制的任务提交方法,包括线程使用详 细信息,时序等等 。 executor 通常用于替代创建多线程。例 如 :你可能会使用以 下 方式来代替创建线 程 集合中的线程
new thread(new(runnabletask())).start()。
executor executor = anexecutor; executor.execute(new runnabletask1()); executor.execute(new runnabletask2());
...
是否还在为ide开发工具频繁失效而烦恼,来吧关注以下公众号获取最新激活方式。亲测可用!
【正版授权,激活自己账号】:
【官方授权 正版激活】:
不过,executor 接口并没有严格地要求执行是异步的。在最简单的情况下,执行程序可以在调用者的线程中立即运行已提交的任务:
class directexecutor implements executor {
public void execute(runnable r) { r.run();
}
}
更常见的是,任务是在某个不是调用者线程的线程中执行的。以下执行程序将为每个任务生成一个新线程。
class threadpertaskexecutor implements executor { public void execute(runnable r) {
new thread(r).start();
}
}
此包中提供的 executor 实现实现了 executorservice,这是一个使用更广泛的接口。threadpoolexecutor类提供一个可扩展的 线程池实现。executors 类为这些 executor 提供了便捷的工厂方法。
java 里面线程池的顶级接口是 executor,但是严格意义上讲 executor 并不是一个线程池,而只是一个执行线程的工具。真正的线
程池接口是 executorservice。
根据线程池的执行策略,executor 的 execute()可能在新线程中执行,或者在线程池中的某个线程中执行,也可能是在调用者线程 中执行。executorservice 在 executor 的基础上增加了两个核心方法:
1、future submit(runnable task)
2、
差异点:这两个方法都可以向线程池提交任务,区别在于 runnable 执行完 run()有返回值,而 callable 执行完 call()后有返回值。 共同点:submit 都返回 future 对象,future 对象可以阻塞线程直到运行完毕,也可以取消任务执行和检测任务是否执行完毕。 在 executors 类里面提供了一些静态工厂,生成一些常用的线程池: 1、newsinglethreadexecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任
务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执 行。
2、newfixedthreadpool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池 的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
3、newcachedthreadpool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲
(60 秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制, 线程池大小完全依赖于操作系统(或者说 jvm)能够创建的最大线程大小。
4、newscheduledthreadpool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
5、newsinglethreadexecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

下面再介绍下 threadpoolexecutor 函数,以便对线程池有进一步认识:
threadpoolexecutor(int corepoolsize, int maximumpoolsize, long keepalivetime, timeunit unit, blockingqueue
rejectedexecutionhandler handler);
corepoolsize: 线程池维护线程的最少数量
maximumpoolsize:线程池维护线程的最大数量
keepalivetime: 线程池维护线程所允许的空闲时间
unit: 线程池维护线程所允许的空闲时间的单位
workqueue: 线程池所使用的缓冲队列
handler: 线程池对拒绝任务的处理策略
当一个任务通过 execute(runnable)方法欲添加到线程池时:
1、如果此时线程池中的数量小于 corepoolsize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
2、如果此时线程池中的数量等于 corepoolsize,但是缓冲队列 workqueue 未满,那么任务被放入缓冲队列。
3、如果此时线程池中的数量大于 corepoolsize,缓冲队列 workqueue 满,并且线程池中的数量小于 maximumpoolsize,建新的线
程来处理被添加的任务。
4、如果此时线程池中的数量大于 corepoolsize,缓冲队列 workqueue 满,并且线程池中的数量等于 maximumpoolsize,那么通过
文章由思创斯整理,转载请注明出处:https://ispacesoft.com/141170.html