瀑布流waterfall的使用以及Bitmap图像优化原理总结

上传人:小** 文档编号:41067338 上传时间:2021-11-18 格式:DOC 页数:28 大小:283KB
收藏 版权申诉 举报 下载
瀑布流waterfall的使用以及Bitmap图像优化原理总结_第1页
第1页 / 共28页
瀑布流waterfall的使用以及Bitmap图像优化原理总结_第2页
第2页 / 共28页
瀑布流waterfall的使用以及Bitmap图像优化原理总结_第3页
第3页 / 共28页
资源描述:

《瀑布流waterfall的使用以及Bitmap图像优化原理总结》由会员分享,可在线阅读,更多相关《瀑布流waterfall的使用以及Bitmap图像优化原理总结(28页珍藏版)》请在装配图网上搜索。

1、瀑布流waterfall 的使用以及Bitmap图像优化原理总结An droid 的Bitmap图像优化的原文链接:An droid 的Bitmap图像优化的译文链接:瀑布流的功能实现目标:1. 瀑布流,可简单配置显示列数。2. 下拉刷新3. 上拉加载更多实现瀑布流的代码目录:d JB com>dodola.model、J* dodowaterfal!A i L7 example.androidbitmapfun.Liti:l:,田 1!bj !jj int&rnal jj P LA_ Ab a L i s tVi ew J a vaA JJ C*LA_Acl a pterVi

2、ew.j ava了 ?L*_rl e d e rVi euvLi st A d a pier ,j ava ,J ;i stView.j a vaT| MuItiColurrinLictViPw.jaua* FB samplejj PullToRefreeh£annpleActivity.jaVia-t meiFriaxwin.view:>£| X Li tView.j ava卜 JT| XLhtViewFoote r.jd vsXListVtewH&ad&r java1、要实现这种特殊的瀑布流布局界面,要自定义个View,自定义View的包: hue

3、wu.pla.libMutiColumnListView -自定义的瀑布流 ViewPLA_ListView瀑布流的显示的方法。MutiColum nListView的父类,主要是对PLA_AbsListView -PLA_ListView的父类,是自定义listview的基类,对绑定数据进行处理。PLA_AdapterView-自定义View的是数据适配器,PLA_AbsListView的父类。PLA_HeaderViewListAdapter 自定义 View 的头布局和尾布局的适配器,在 PLA_AbsListView 用到。2、 要实现上拉下拉功能,需要对 MutiColum nLis

4、tView进行重写,把头尾 和各种手势处理加上:me.maxwi n. viewXListView对MutiColumnListView进行重写,把头尾和各种手势处理加上,项目中直接用到的类。XListViewFooter添加的尾布局。XListViewHeader添加的头布局。3、这里瀑布流加载的是网络图片,图片下载显示工具包:com.example.a ndroid.bitmapfu n.utilbitmapfun 是google教程提供的工具包,是对图片的异步加载、缓 存的工具,使用很简单,就一个方法把图片 url和imageview控件传进去就 可以。其显现逻辑感兴趣的可以学一下。4、

5、由于瀑布流图片显示的自动调整宽高,就要对 imageview进行重写: com/dodowaterfall/widget/ScalelmageView.javawidget 包里的另外还有两个自定义 View不知道干啥使得,项目中也 没用到,暂时先不管了。5、工具包和自定义view准备好,调用自己界面显示瀑布流: com/huewu/pla/sample/PullToRefreshSampleActivity.java图片数据显示首先通过网络获得图片的数据,图片数据的实体类包:com.dodola.model再按照实现流程分析下,瀑布流功能的实现逻辑:1获取网络图片数据,http+jso n流

6、程没必要说,看下获得的数据:try if ( null != json) JSONObject n ewsObject =new JSONObject(jso n);JSONObject jso nO bject = n ewsObject.getJSONObject("data");JSONArray blogsJs on = jso nObject.getJSONArray("blogs");for ( int i =0; i < blogsJson.length(); i+) JSONObject newsI nfoLeftObject =

7、blogsJs on .getJSONObject(i);Duita nglnfo n ews Info1 =new Duita nglnfo();n ewsI nfo1.setAlbid( newsI nfoLeftObject.isNull(wsI nfoLeftObject.getStri ng("albid");n ewsI nfo1.setIsrc( newsI nfoLeftObject.isNull(In foLeftObject.getStri ng("isrc");n ewsI nfo1.setMsg( newsI nfoLeftObj

8、ect.isNull(foLeftObject.getString("msg");n ewsI nfo1.setHeight( newsI nfoLeftObject.getI nt(duita ngs.add( news In fo1); catch (JSONException e) "albid" ) ?"" : ne"isrc" ) ?"" : news"msg" ) ?"" : newsIn"iht");e.pri ntSta

9、ckTrace();获得id、isrc、msg这三个一看就知道是什么,iht这个是图片的高,刚看 的时候,不知道具体是干啥用的,肯定是来控制图片的显示宽高。2、自定义 adapter 对imageview 设置数据:Overridepublic View getView( int positi on. View con vertView, ViewGroup pare nt) ViewHolder holder;Duitanglnfo duitanglnfo = mlnfos.get (position);if (convertView =null ) Layout In flater lay

10、out In flator = Layout In flater.from (pare nt.getC on text();convertView = layoutInflator.inflate(R.layout.infos_list,null );holder =new ViewHolder();holder.imageView = (ScaleImageView) con vertView.fi ndViewByld(R.id. news_pic);holder.c onten tView = (TextView) con vertView.fi ndViewByld(R.id. new

11、s_title);con vertView.setTag(holder);holder = (ViewHolder) con vertView.getTag();holder.imageView.setlmageWidth(duita ngl nfo.getWidth();holder.imageView.setlmageHeight(duita ngl nfo.getHeight();holder.c onten tView.setText(duita ngl nfo.getMsg();mlmageFetcher.loadlmage(duita ngln fo.getlsrc(), hold

12、er.imageView);retur ncon vertView;这里设置了 imageview的图片资源的宽高,我们现在至少知道高是从网络获得的,宽哪来的:public int getWidth()return 200;这里是固定的200,可以推测我们获取的高的值,是相对于宽200的相对值c3、那Imageview 是的实际宽高是在自定义ScalelmageView 里动态计算的:Overrideprotected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) int widthMode = MeasureSpec

13、.getMode(widthMeasureSpec);super .onMeasure(widthMeasureSpec, heightMeasureSpec);super .onMeasure(widthMeasureSpec, heightMeasureSpec);intintwidth = MeasureSpec.getSize(widthMeasureSpec);height = MeasureSpec.getSize(heightMeasureSpec);super .onMeasure(widthMeasureSpec, heightMeasureSpec);super .onMe

14、asure(widthMeasureSpec, heightMeasureSpec);* if both width and height are set scale width first. modify in future* if n ecessary*/if (widthMode = MeasureSpec.EXACTLY | widthMode = MeasureSpec.AT_MOST) scaleToWidth =true else if (heightMode = MeasureSpec.EXACTLY | heightMode = MeasureSp ec.AT_MOST) s

15、caleToWidth =false elsethrownew IllegalStateExceptio n("width or height n eeds to be set to match_pare nt or a specific dime nsion");if (imageWidth =0) / nothing to measurereturn else if (scaleToWidth) int iw = imageWidth;int ih = imageHeight;int heightC = width * ih / iw;if (height >0)

16、if (heightC > height) / dont let hegiht be greater the n set maxheightC = height;width = heightC * iw / ih;this .setScaleType(ScaleType.CENTER_CROP);setMeasuredDime nsio n(width, heightC); else / n eed to scale to height in steadint marg =0;int marg =0;if (getParent() !=null ) int marg =0;int mar

17、g =0;P();null ) if (getPare nt().getPare nt() != marg += (RelativeLayout) getPare nt().getPare nt().getPadd in gToint marg =0;int marg =0;marg += (RelativeLayout) getPare nt().getPare nt().getPadd in gBoint marg =0;int marg =0;ttom();int marg =0;int marg =0;int iw = imageWidth;int ih = imageHeight;w

18、idth = height * iw / ih;height -= marg;setMeasuredDime nsio n(width, height);以上根据宽高属性设置的判断,对实际宽高进行重新设置,先看下布局文件 宽高设置:vme.maxwi n.view.XListViewxmlns:pla="http: / apk/ res-auto "an droid:id="+id/list"an droid:layout_width="match_pare nt"an droid:layout_height="match_

19、pare nt"an droid:fastScrollE nabled="true"an droid:scrollbars="vertical"pla:plaColum nN umber="3" />那就是scaleToWidth = true;根据图片资源的宽高比计算出iamgeview的高:int heightC = width * ih / iw;图片居中显示。根据瀑布流显示列数和边界可以计算出显示图片的imageview的宽上面还限制了 imageview显示高的上限,如果超过的话,就来缩小 imageview

20、 的宽,也就是宽不一定是 match_parent 。4、自定义MultiColumnListView的实现原理创建瀑布流view时候首先初始化列数:private void in it(AttributeSet attrs) getWi ndowVisibleDisplayFrame(mFrameRect);if (attrs =null ) mColumnNumber = (DEFAULT_COLUMN_NUMBER);II default column number is/ 2.else TypedArray a = getContext().obtainStyledAttributes

21、(attrs, R.styleable.PinterestLikeAdapterView);int lan dColNumber = a.getl nteger(R.styleable.Pi nterestLikeAdapterView_plaLan dscapeColu mn Number,3);int defColNumber = a.getl nteger(R.styleable.P in terestLikeAdapterView_plaColum nN umber, DEFAULT_COLUMN_NUMBER);1) if (mFrameRect.width() > mFram

22、eRect.height() && lan dColNumber !=-mColum nN umber = (la ndColNumber); else if (defColNumber != -1) mColum nN umber = (defColNumber); else mColum nN umber = (DEFAULT_COLUMN_NUMBER);mColu mn Padd in gLeft = a.getDime nsion PixelSize(R.styleable.P in terestLikeAdapterView_plaColu mn Padd in g

23、Left,0);mColu mn Padd in gRight = a.getDime nsio nPixelSize(R.styleable.Pi nterestLikeAdapterView_plaColum nPaddi ngRight,0);a.recycle();mColu mns =new Colum n getColum nN umber();for ( int i =0; i < getColumnNumber。; +i)mColu mn si =new Colu mn (i);mFixedColum n =new FixedColum n();可以看出列数没有设置的话,

24、会有一个默认值:DEFAULT_COLUMN_NUMBER根据设置的列数,定义了一个列数组,在存储每一列的数据:mColum ns =new Colu mn getColu mnNu mber();初始化每一列的宽度和横向位置:Overrideprotected void onM easure(int widthMeasureSpec, int heightMeasureSpec) super.o nM easure(widthMeasureSpec, heightMeasureSpec);colum nWidth = (getMeasuredWidth() - mListPaddi ng.l

25、eft - mListPaddi ng.right - mColu mn Paddi ngLeft - mColu mn Padd in gRight)/ getColu mn Number。;for ( intin dex = 0; in dex < getColu mn Number。; +index ) mColum nsmColum ns+ colu mn Widthindex ;index .mColumnWidth = columnWidth;index .mColumnLeft = mListPadding.left + mColumnPaddingLeftmFixedCo

26、lum n. mColum nLeft = mListPaddi ng.left;mFixedColu mn .mColum nWidth = getMeasuredWidth();接下来就是想每一列中添加数据显示了,大体原理就是:1判断是在在头部添加还是尾部添加,也就是上拉还是下拉。2、通过计算对比每一列的高,在最短的一列添加上要添加的数据。3、根据添加后的数据,刷新布局显示。BitmapFu n 解析通过Bitm apFu n在项目中使用,结合代码了解一下 Bit map Fu n加载图片的原 理,以及最佳使用实践。本文说明不包括BitmapFun的缓存部分。An droid开发在使用Li

27、stView 和GridView时,可能会有很多网络图片需要 加载,通常我们会为每个图片加载启动一个 Thread或者直接使用官方提供的AsyncTask,来做Http异步加载,但当每个ImageView子视图都触发一个AsyncTask来异步加载图片时,这样就会产生如下问题:1. 当用户快速滑动时,ImageView已经被回收,而绑定的线程还在运行,浪 费CPU浪费内存。无法确保当前视图在结束时,分配的视图已经进入循环队列中给另外一个 子视图进行重用,意思就是,图片显示错位了,不该显示到当前问题的图片却显示了,这个是经常遇到的问题。可以结合Adapter中的getView方法的convert

28、View 参数理解,ListView 是回收和重复利用item的。3.无法确保所有的异步任务能够按顺序执行。在这些问题下,官网给出的答案是,使用下面的方法来保证:1. ImageView 和Task绑定准确的加载对应图片;2. ImageView 和Task无法对应时则取消任务;12class Asyn cDrawable exte ndsBitmapDrawable.234567891011121314boolea n can celPote ntialWork(Stri ng url, ImageView imageView).ImageViewResizeTask getBitmapWo

29、rkerTask(lmageView imageView).具体代码实现如下:/* 扩展BitmapDrawable 类,通过弱引用关联任务 BitmapWorkerTask* BitmapDrawable被用来作为占位图片,绑定任务到ImageView 中*/private class Asyn cDrawable exte ndsBitmapDrawable private finalWeakRefere nce<BitmapWorkerTask> viewResizeTaskRefere nee;publicAsyn cDrawable(Resources res, Bitm

30、ap bitmap,BitmapWorkerTask viewResizeTask) super(res, bitmap);viewResizeTaskRefere nee = newWeakRefere nce<BitmapWorkerTask>(viewResizeTask);16public BitmapWorkerTask getBitmapWorkerTask() returnviewResizeTaskRefere nce.get();/*确保ImageView执行的是它对应的Task,否则取消任务* param url* param imageView* return

31、*/private boolea n can celPote ntialWork(Stri ng url, ImageView imageView) / 获得ImageView对应的Taskfinal BitmapWorkerTask bitmapWorkerTask =getBitmapWorkerTask(imageView);if(bitm apWorkerTask != n ull) finalStri ng imgUrl = bitmapWorkerTask.url;if(imgUrl = n ull| !imgUrl.equals(url) / Can cel previous t

32、askbitmapWorkerTask.ca ncel(true); else/ The same work is already in progressreturnfalse;/ No task associated with the ImageView,1718192021222324252627282930313233343536373839404142434445464748/or an exist ing task was can celled49returntrue;50515253545556*异步加载图片2345678*获得已经被分配到ImageView的指定的Task* pa

33、ram imageView* return*/private BitmapWorkerTask getBitmapWorkerTask(lmageView imageView) if (imageView != n ull) finalDrawable drawable = imageView.getDrawable();if(drawable in sta nceofAsyn cDrawable) finalAsyn cDrawable asyn cDrawable =(Asyn cDrawable) drawable;returnasyn cDrawable.getBitmapWorker

34、Task();return n ull;* param url* param imageView*/private void loadBitmap(Stri ng url, ImageView imageView) if(ca ncelPote ntialWork(url, imageView) finalBitmapWorkerTask task = new BitmapWorkerTask(imageView);finalAsyn cDrawable asyn cDrawable = newAsyn cDrawable(con text.getResources(), n ull, tas

35、k);imageView.setlmageDrawable(as yn cDrawable);task.execute(url);/*异步加载图片Task类*/class BitmapWorkerTask exte ndsAsyn cTask<I nteger, Void, Bitmap> Overrideprotected void onPostExecute(Bitmap bitmap) if(isCa ncelled() bitmap = n ull;if(imageViewRefere nee != n ull&& bitmap != nu II) fina

36、lImageView imageView = imageViewRefere nce.get();finalBitmapWorkerTask bitmapWorkerTask =getBitmapWorkerTask(imageView);if(this = bitmapWorkerTask && imageView != n ull) imageView.setlmageBitmap(bitmap);91011121314151617181920212223242526272829303132333435最佳使用实践,提高流畅度1.设置 ListView的 OnScrollL

37、istener图片事件,在滑动的时候不加载public void onScrollStateChanged(AbsListView view, intscrollState) 1if(scrollState = AbsListView.O nScrollListe ner.SCROLL_STATE_FLING) if(!Utils.hasHo neycomb() mlmageFetcher.setPauseWork(true); elsemlmageFetcher.setPauseWork(false);2.在 Activity或 Fragment 的 onResume() , onPause

38、(),on Destroy()方法中调用恰当方法非常有用Overridepublic void on Resume() super.o nResume();mlmageFetcher.setExitTasksEarly(false);Overridepublic void on Pause() super.o nPause();12mlmageFetcher.setPauseWork(false);9101113mlmageFetcher.setExitTasksEarly(true);141516171819mlmageFetcher.flushCache();Overridepublic

39、void on Destroy。super.o nDestroy();mlmageFetcher.closeCache();BitmapFu n的类解释:hubst aidua抚tEemg;WiAML£榔1 4皿片和:略鳩油di*zKUiliae 3 如RAUI "L-if ftMhMFi*4*ll lal«+临1同饵4|14占暉裤d整ImageWorker的功能,从内存直接加载或异步加载(从磁盘缓存或网络下载) 图片。缓存的实现-ImageCache, 异步加载的实现-BitmapWorkerTask。是不是比较清晰了。接下来继续往下看:ImageResizer

40、 :继承自ImageWorker,可能有的童鞋会问ImageWorker不是 已经实现异步和缓存了吗,这个类是干嘛的呢?这个主要是根据给定的大小对 Image做调整。比如当图片太大时,不能简单的加载到内存,需要做大小调整 处理。这里对它的几个主要接口说明一下:setImageSize :设置图片要调整的大小calculateInSampleSize:计算缩放比例-根据原图大小和要调整后的大小计算decodeSampledBitmapFrom*:得到调整大小后的图片,这里好几个方法,数据源不一样而已,没啥大区别。ImageFetcher :继承自ImageResizer。从网络下载图片。这里要澄

41、清一点, processBitmap 在ImageWorker中是一个抽象方法,并没有实现体,在本示例中,是在 ImageFetcher中实现的。之所以这样设计,是因为图片的来源是不确定 和可变的,有可能从网络下载,有可能从本地数据库获取。如果图片资源是静态的,当我们要在View上显示图片时,只需要简单的将图片 赋值给ImageView就可以了,但如果需要浏览网络上的图片时该如何做呢?有可能图片很大,有可能网速很慢并且不稳定,这种情况下该如何增加 用户体验。An droid官方的BitmapFu n示例程序已经给了我们很好的解决方法-其实万变不离其中,还是采用了提升性能的两种常用方法:异步和

42、缓存。不多说我们先来看BitmapFun的主要类图:ImageWorker :这个是加载图片的核心类,建议大家看源代码从这个类看起。它的主要功能是从内存/磁盘缓存中加载图片,或者是从网络上下载。这里第一要使用缓存,第二从网络上下载,必然 要使用异步线程,所以这里从类图中大家也可以看到它有两个关联类Bit map WorkerTask( 继承自 Asy nTask)和 ImageCache, 分别用来处理异步和缓存。ImageWorker提供给外部的主要接口是loadimage方法-加载图片,如果内 存中有,直接加载。否则使用异步线程(BitmapWorkerTask )后台加载-从 磁盘或者是

43、网络上下载BitmapWorkerTask:异步处理图片-下载并绑定图片ImageCache:图片的缓存处理,这里使用了二级缓存:内存和磁盘。这里从类图也可以看到它有一个关联类 DiskLruCache 。DiskLruCache:关于这个类网上有一些详尽的解释文章。在看这个类时切忌一开始就看代码,一定要先看类的说明,主要是 journal file 的格式,否则 你就很难明白它的一些代码为什么那么写。这里把几个重点提一下,相信大家 再看代码会容易的多1前5行是固定(最开始是固定的5行,值是可变)2 一条记录用类Entry来描述,一条记录就是一个 Entry实例,比如 CLEAN 340033

44、0d1dfc7f3f7f4b8d4d803dfcf6 832 21054在程序中就是一个Entry实例3 Editor 是Entry的操作器,用来读写数据>3dTEL1*Lpevt114叙味前非誘贾洋w强IUD11III*iUtI4写到这里先停一下,我们再次说明ImageWorker的功能,从内存直接加载或异 步加载(从磁盘缓存或网络下载)图片。缓存的实现 -ImageCache,异步加载 的实现-Bitm apWorkerTask 。是不是比较清晰了。接下来继续往下看:ImageResizer :继承自ImageWorker,可能有的童鞋会问ImageWorker不是 已经实现异步和缓

45、存了吗,这个类是干嘛的呢?这个主要是根据给定的大小对 Image做调整。比如当图片太大时,不能简单的加载到内存,需要做大小调整 处理。这里对它的几个主要接口说明一下:setImageSize :设置图片要调整的大小calculateInSampleSize:计算缩放比例-根据原图大小和要调整后的大小计算decodeSampledBitmapFrom*:得到调整大小后的图片,这里好几个方法,数据源不一样而已,没啥大区别。ImageFetcher :继承自ImageResizer。从网络下载图片。这里要澄清一点, processBitmap 在ImageWorker中是一个抽象方法,并没有实现体,

46、在本示例中,是在 ImageFetcher中实现的。之所以这样设计,是因为图片的来源是不确定 和可变的,有可能从网络下载,有可能从本地数据库获取。View这一层基为例:最后就是在View这一层如何来使用了,从类图中可以看出, 本上操作 ImageFetcher 就可以了。以 IamgeGridFragment,并且添加缓存处理实例1 在 on Create 中实例化 ImageFetcher|V*I I kA*T£Jjd,feCU.i riifc-*I3 . ohLm IU IUtH I I:jMiflffKM EfWH wIEt cf 1.4443131 Wa#*ii ufH Mt

47、61 丄IMGK21KffE?>=lkK.QeUjptTMir:±Ee?u-ia±l.2 on CreateView中异步加载图片EKZCnEl£FI.HAdr=<-3.Im ageAdapter.getView -调用 ImageFetcher.loadlmage加载图片=£5二CCjCTt«Tj.aniTClJMI, '/Winop =XU-3t7 IBJHeMPHHW« ;4MH4H < IlMCI feBlTVMtT 1JI MlttLIt -. LM霁Ell t?4CK3 :»|HJWrDemo 的下载地址是:

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!