Context部分

View的构造函数

View.java

        
  1. /**
  2. *Simpleconstructortousewhencreatingaviewfromcode.
  3. *
  4. *@paramcontextTheContexttheviewisrunningin,throughwhichitcan
  5. *accessthecurrenttheme,resources,etc.
  6. */
  7. publicView(Contextcontext){
  8. mContext=context;
  9. mResources=context!=null?context.getResources():null;
  10. mViewFlags=SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED;
  11. //Usedfordebugonly
  12. //++sInstanceCount;
  13. mTouchSlop=ViewConfiguration.get(context).getScaledTouchSlop();
  14. }

View 保存了对context的引用,mContext = context;

1.我们知道结构其实和DOM差不多,都会保存其父容器、子容器的引用,因而context的使用需要注意,不要使用静态的子View

2.来看View中的setBackgroundDrawable方法

View.java

        
  1. /**
  2. *SetthebackgroundtoagivenDrawable,orremovethebackground.Ifthe
  3. *backgroundhaspadding,thisView'spaddingissettothebackground's
  4. *padding.However,whenabackgroundisremoved,thisView'spaddingisn't
  5. *touched.Ifsettingthepaddingisdesired,pleaseuse
  6. *{@link#setPadding(int,int,int,int)}.
  7. *
  8. *@paramdTheDrawabletouseasthebackground,ornulltoremovethe
  9. *background
  10. */
  11. publicvoidsetBackgroundDrawable(Drawabled){
  12. booleanrequestLayout=false;
  13. mBackgroundResource=0;
  14. /*
  15. *Regardlessofwhetherwe'resettinganewbackgroundornot,wewant
  16. *toclearthepreviousdrawable.
  17. */
  18. if(mBGDrawable!=null){
  19. mBGDrawable.setCallback(null);
  20. unscheduleDrawable(mBGDrawable);
  21. }
  22. if(d!=null){
  23. Rectpadding=sThreadLocal.get();
  24. if(padding==null){
  25. padding=newRect();
  26. sThreadLocal.set(padding);
  27. }
  28. if(d.getPadding(padding)){
  29. setPadding(padding.left,padding.top,padding.right,padding.bottom);
  30. }
  31. //ComparetheminimumsizesoftheoldDrawableandthenew.Ifthereisn'tanoldor
  32. //ifithasadifferentminimumsize,weshouldlayoutagain
  33. if(mBGDrawable==null||mBGDrawable.getMinimumHeight()!=d.getMinimumHeight()||
  34. mBGDrawable.getMinimumWidth()!=d.getMinimumWidth()){
  35. requestLayout=true;
  36. }
  37. d.setCallback(this);
  38. if(d.isStateful()){
  39. d.setState(getDrawableState());
  40. }
  41. d.setVisible(getVisibility()==VISIBLE,false);
  42. mBGDrawable=d;
  43. if((mPrivateFlags&SKIP_DRAW)!=0){
  44. mPrivateFlags&=~SKIP_DRAW;
  45. mPrivateFlags|=ONLY_DRAWS_BACKGROUND;
  46. requestLayout=true;
  47. }
  48. }else{
  49. /*Removethebackground*/
  50. mBGDrawable=null;
  51. if((mPrivateFlags&ONLY_DRAWS_BACKGROUND)!=0){
  52. /*
  53. *ThisviewONLYdrewthebackgroundbeforeandwe'reremoving
  54. *thebackground,sonowitwon'tdrawanything
  55. *(henceweSKIP_DRAW)
  56. */
  57. mPrivateFlags&=~ONLY_DRAWS_BACKGROUND;
  58. mPrivateFlags|=SKIP_DRAW;
  59. }
  60. /*
  61. *Whenthebackgroundisset,wetrytoapplyitspaddingtothis
  62. *View.Whenthebackgroundisremoved,wedon'ttouchthisView's
  63. *padding.ThisisnotedintheJavadocs.Hence,wedon'tneedto
  64. *requestLayout(),theinvalidate()belowissufficient.
  65. */
  66. //Theoldbackground'sminimumsizecouldhaveaffectedthis
  67. //View'slayout,solet'srequestLayout
  68. requestLayout=true;
  69. }
  70. computeOpaqueFlags();
  71. if(requestLayout){
  72. requestLayout();
  73. }
  74. mBackgroundSizeChanged=true;
  75. invalidate();
  76. }

我们注意到d.setCallback(this);

Drawable保存了View的引用,处理了一些回调。因此,Drawable对象使用时需要注意了。不要作为静态对象使用。

Resource.getDrewable()方法是比较好的,Resource内部使用了一个Drawable.ConstantState的弱引用缓存,提高了效率。

来看代码:

Resource.java

        
  1. /*package*/DrawableloadDrawable(TypedValuevalue,intid)
  2. throwsNotFoundException{
  3. if(TRACE_FOR_PRELOAD){
  4. //Logonlyframeworkresources
  5. if((id>>>24)==0x1){
  6. finalStringname=getResourceName(id);
  7. if(name!=null)android.util.Log.d("PreloadDrawable",name);
  8. }
  9. }
  10. finallongkey=(((long)value.assetCookie)<<32)|value.data;
  11. Drawabledr=getCachedDrawable(key);
  12. if(dr!=null){
  13. returndr;
  14. }
  15. Drawable.ConstantStatecs=sPreloadedDrawables.get(key);
  16. if(cs!=null){
  17. dr=cs.newDrawable(this);
  18. }else{
  19. if(value.type>=TypedValue.TYPE_FIRST_COLOR_INT&&
  20. value.type<=TypedValue.TYPE_LAST_COLOR_INT){
  21. dr=newColorDrawable(value.data);
  22. }
  23. if(dr==null){
  24. if(value.string==null){
  25. thrownewNotFoundException(
  26. "ResourceisnotaDrawable(colororpath):"+value);
  27. }
  28. Stringfile=value.string.toString();
  29. if(DEBUG_LOAD)Log.v(TAG,"Loadingdrawableforcookie"
  30. +value.assetCookie+":"+file);
  31. if(file.endsWith(".xml")){
  32. try{
  33. XmlResourceParserrp=loadXmlResourceParser(
  34. file,id,value.assetCookie,"drawable");
  35. dr=Drawable.createFromXml(this,rp);
  36. rp.close();
  37. }catch(Exceptione){
  38. NotFoundExceptionrnf=newNotFoundException(
  39. "File"+file+"fromdrawableresourceID#0x"
  40. +Integer.toHexString(id));
  41. rnf.initCause(e);
  42. throwrnf;
  43. }
  44. }else{
  45. try{
  46. InputStreamis=mAssets.openNonAsset(
  47. value.assetCookie,file,AssetManager.ACCESS_STREAMING);
  48. //System.out.println("Openedfile"+file+":"+is);
  49. dr=Drawable.createFromResourceStream(this,value,is,
  50. file,null);
  51. is.close();
  52. //System.out.println("Createdstream:"+dr);
  53. }catch(Exceptione){
  54. NotFoundExceptionrnf=newNotFoundException(
  55. "File"+file+"fromdrawableresourceID#0x"
  56. +Integer.toHexString(id));
  57. rnf.initCause(e);
  58. throwrnf;
  59. }
  60. }
  61. }
  62. }
  63. if(dr!=null){
  64. dr.setChangingConfigurations(value.changingConfigurations);
  65. cs=dr.getConstantState();
  66. if(cs!=null){
  67. if(mPreloading){
  68. sPreloadedDrawables.put(key,cs);
  69. }else{
  70. synchronized(mTmpValue){
  71. //Log.i(TAG,"Savingcacheddrawable@#"+
  72. //Integer.toHexString(key.intValue())
  73. //+"in"+this+":"+cs);
  74. mDrawableCache.put(key,newWeakReference<Drawable.ConstantState>(cs));
  75. }
  76. }
  77. }
  78. }
  79. returndr;
  80. }

使用Drawable一般情况下效率较高,且不易发生内存泄露。

接下来我们来看下BitMap的使用

BitMapFactory.java

        
  1. /**
  2. *Decodeaninputstreamintoabitmap.Iftheinputstreamisnull,or
  3. *cannotbeusedtodecodeabitmap,thefunctionreturnsnull.
  4. *Thestream'spositionwillbewhereeveritwasaftertheencodeddata
  5. *wasread.
  6. *
  7. *@paramisTheinputstreamthatholdstherawdatatobedecodedintoa
  8. *bitmap.
  9. *@paramoutPaddingIfnotnull,returnthepaddingrectforthebitmapif
  10. *itexists,otherwisesetpaddingto[-1,-1,-1,-1].If
  11. *nobitmapisreturned(null)thenpaddingis
  12. *unchanged.
  13. *@paramoptsnull-ok;Optionsthatcontroldownsamplingandwhetherthe
  14. *imageshouldbecompletelydecoded,orjustissizereturned.
  15. *@returnThedecodedbitmap,ornulliftheimagedatacouldnotbe
  16. *decoded,or,ifoptsisnon-null,ifoptsrequestedonlythe
  17. *sizebereturned(inopts.outWidthandopts.outHeight)
  18. */
  19. publicstaticBitmapdecodeStream(InputStreamis,RectoutPadding,Optionsopts){
  20. //wedon'tthrowinthiscase,thusallowingthecallertoonlycheck
  21. //thecache,andnotforcetheimagetobedecoded.
  22. if(is==null){
  23. returnnull;
  24. }
  25. //weneedmark/resettoworkproperly
  26. if(!is.markSupported()){
  27. is=newBufferedInputStream(is,16*1024);
  28. }
  29. //sowecancallreset()ifagivencodecgivesupafterreadingupto
  30. //thismanybytes.FIXME:needtofindoutfromthecodecswhatthis
  31. //valueshouldbe.
  32. is.mark(1024);
  33. Bitmapbm;
  34. if(isinstanceofAssetManager.AssetInputStream){
  35. bm=nativeDecodeAsset(((AssetManager.AssetInputStream)is).getAssetInt(),
  36. outPadding,opts);
  37. }else{
  38. //passsometempstoragedowntothenativecode.1024ismadeup,
  39. //butshouldbelargeenoughtoavoidtoomanysmallcallsback
  40. //intois.read(...)Thisnumberisnotrelatedtothevaluepassed
  41. //tomark(...)above.
  42. byte[]tempStorage=null;
  43. if(opts!=null)
  44. tempStorage=opts.inTempStorage;
  45. if(tempStorage==null)
  46. tempStorage=newbyte[16*1024];
  47. bm=nativeDecodeStream(is,tempStorage,outPadding,opts);
  48. }
  49. returnfinishDecode(bm,outPadding,opts);
  50. }

我们每次调用BitMapFactory中的生产bitmap的方法的时候都会new一个bitmap出来,为了避免内存溢出,我们有两种主要的思路:

1. 使用缓存,避免重复new同一个图片

2. 销毁bitmap,使用完之后立刻销毁bitmap

缓存需要自己实现,如果是销毁的话,可以使用Bitmap中的recycle()方法。

更多相关文章

  1. Android中Timer与TimerTask的使用 间隔执行
  2. Android(安卓)SwitchButton(滑动开关)
  3. Spinner 使用方法小结
  4. 【ClassNotFoundExcept】Android应用程序启动时发生AndroidRunti
  5. Android(安卓)Device Monitor 报 open failed: Permission denie
  6. Android中利用画图类和线程画出闪烁的心形
  7. Android-中常用方法集锦
  8. Android(安卓)首选网络模式默认值的修改方法
  9. android 中如何限制 EditText 最大输入字符数(2)

随机推荐

  1. Android应用程序键盘(Keyboard)消息处理机
  2. FregServer进程,获取ServiceManager代理对
  3. Android(安卓)Studio查看错误信息
  4. 百度地图android开发资料
  5. Android(安卓)通过按键旋转屏幕
  6. 2011.07.19——— android intent 传递li
  7. 高德地图自定义点聚合样式Android
  8. android 实现模拟按键
  9. Android(安卓)Visualizer
  10. 关于Android启动页全屏的解决方案