android oom 代码注意



View.java

1. /**
2.
3. * Simple constructor to use when creating a view from code.
4.
5. *
6.
7. * @param context The Context the view is running in, through which it can
8.
9. * access the current theme, resources, etc.
10.
11. */
12.
13. public View(Context context) {
14.
15. mContext = context;
16.
17. mResources = context != null ? context.getResources() : null;
18.
19. mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
20.
21. // Used for debug only
22.
23. //++sInstanceCount;
24.
25. mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
26.
27. }

View 保存了对context的引用,mContext = context;
1.我们知道结构其实和DOM差不多,都会保存其父容器、子容器的引用,因而context的使用需要注意,不要使用静态的子View。
2.来看View中的setBackgroundDrawable方法
View.java

1. /**
2.
3. * Set the background to a given Drawable, or remove the background. If the
4.
5. * background has padding, this View's padding is set to the background's
6.
7. * padding. However, when a background is removed, this View's padding isn't
8.
9. * touched. If setting the padding is desired, please use
10.
11. * {@link #setPadding(int, int, int, int)}.
12.
13. *
14.
15. * @param d The Drawable to use as the background, or null to remove the
16.
17. * background
18.
19. */
20.
21. public void setBackgroundDrawable(Drawable d) {
22.
23. boolean requestLayout = false;
24.
25.
26.
27. mBackgroundResource = 0;
28.
29.
30.
31. /*
32.
33. * Regardless of whether we're setting a new background or not, we want
34.
35. * to clear the previous drawable.
36.
37. */
38.
39. if (mBGDrawable != null) {
40.
41. mBGDrawable.setCallback(null);
42.
43. unscheduleDrawable(mBGDrawable);
44.
45. }
46.
47.
48.
49. if (d != null) {
50.
51. Rect padding = sThreadLocal.get();
52.
53. if (padding == null) {
54.
55. padding = new Rect();
56.
57. sThreadLocal.set(padding);
58.
59. }
60.
61. if (d.getPadding(padding)) {
62.
63. setPadding(padding.left, padding.top, padding.right, padding.bottom);
64.
65. }
66.
67.
68.
69. // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
70.
71. // if it has a different minimum size, we should layout again
72.
73. if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
74.
75. mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
76.
77. requestLayout = true;
78.
79. }
80.
81.
82.
83. d.setCallback(this);
84.
85. if (d.isStateful()) {
86.
87. d.setState(getDrawableState());
88.
89. }
90.
91. d.setVisible(getVisibility() == VISIBLE, false);
92.
93. mBGDrawable = d;
94.
95.
96.
97. if ((mPrivateFlags & SKIP_DRAW) != 0) {
98.
99. mPrivateFlags &= ~SKIP_DRAW;
100.
101. mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
102.
103. requestLayout = true;
104.
105. }
106.
107. } else {
108.
109. /* Remove the background */
110.
111. mBGDrawable = null;
112.
113.
114.
115. if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
116.
117. /*
118.
119. * This view ONLY drew the background before and we're removing
120.
121. * the background, so now it won't draw anything
122.
123. * (hence we SKIP_DRAW)
124.
125. */
126.
127. mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
128.
129. mPrivateFlags |= SKIP_DRAW;
130.
131. }
132.
133.
134.
135. /*
136.
137. * When the background is set, we try to apply its padding to this
138.
139. * View. When the background is removed, we don't touch this View's
140.
141. * padding. This is noted in the Javadocs. Hence, we don't need to
142.
143. * requestLayout(), the invalidate() below is sufficient.
144.
145. */
146.
147.
148.
149. // The old background's minimum size could have affected this
150.
151. // View's layout, so let's requestLayout
152.
153. requestLayout = true;
154.
155. }
156.
157.
158.
159. computeOpaqueFlags();
160.
161.
162.
163. if (requestLayout) {
164.
165. requestLayout();
166.
167. }
168.
169.
170.
171. mBackgroundSizeChanged = true;
172.
173. invalidate();
174.
175. }
我们注意到d.setCallback(this);
即Drawable保存了View的引用,处理了一些回调。因此,Drawable对象使用时需要注意了。不要作为静态对象使用。www.2cto.com

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

1. /*package*/ Drawable loadDrawable(TypedValue value, int id)
2.
3. throws NotFoundException {
4.
5.
6.
7. if (TRACE_FOR_PRELOAD) {
8.
9. // Log only framework resources
10.
11. if ((id >>> 24) == 0x1) {
12.
13. final String name = getResourceName(id);
14.
15. if (name != null) android.util.Log.d("PreloadDrawable", name);
16.
17. }
18.
19. }
20.
21.
22.
23. final long key = (((long) value.assetCookie) << 32) | value.data;
24.
25. Drawable dr = getCachedDrawable(key);
26.
27.
28.
29. if (dr != null) {
30.
31. return dr;
32.
33. }
34.
35.
36.
37. Drawable.ConstantState cs = sPreloadedDrawables.get(key);
38.
39. if (cs != null) {
40.
41. dr = cs.newDrawable(this);
42.
43. } else {
44.
45. if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
46.
47. value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
48.
49. dr = new ColorDrawable(value.data);
50.
51. }
52.
53.
54.
55. if (dr == null) {
56.
57. if (value.string == null) {
58.
59. throw new NotFoundException(
60.
61. "Resource is not a Drawable (color or path): " + value);
62.
63. }
64.
65.
66.
67. String file = value.string.toString();
68.
69.
70.
71. if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "
72.
73. + value.assetCookie + ": " + file);
74.
75.
76.
77. if (file.endsWith(".xml")) {
78.
79. try {
80.
81. XmlResourceParser rp = loadXmlResourceParser(
82.
83. file, id, value.assetCookie, "drawable");
84.
85. dr = Drawable.createFromXml(this, rp);
86.
87. rp.close();
88.
89. } catch (Exception e) {
90.
91. NotFoundException rnf = new NotFoundException(
92.
93. "File " + file + " from drawable resource ID #0x"
94.
95. + Integer.toHexString(id));
96.
97. rnf.initCause(e);
98.
99. throw rnf;
100.
101. }
102.
103.
104.
105. } else {
106.
107. try {
108.
109. InputStream is = mAssets.openNonAsset(
110.
111. value.assetCookie, file, AssetManager.ACCESS_STREAMING);
112.
113. // System.out.println("Opened file " + file + ": " + is);
114.
115. dr = Drawable.createFromResourceStream(this, value, is,
116.
117. file, null);
118.
119. is.close();
120.
121. // System.out.println("Created stream: " + dr);
122.
123. } catch (Exception e) {
124.
125. NotFoundException rnf = new NotFoundException(
126.
127. "File " + file + " from drawable resource ID #0x"
128.
129. + Integer.toHexString(id));
130.
131. rnf.initCause(e);
132.
133. throw rnf;
134.
135. }
136.
137. }
138.
139. }
140.
141. }
142.
143.
144.
145. if (dr != null) {
146.
147. dr.setChangingConfigurations(value.changingConfigurations);
148.
149. cs = dr.getConstantState();
150.
151. if (cs != null) {
152.
153. if (mPreloading) {
154.
155. sPreloadedDrawables.put(key, cs);
156.
157. } else {
158.
159. synchronized (mTmpValue) {
160.
161. //Log.i(TAG, "Saving cached drawable @ #" +
162.
163. // Integer.toHexString(key.intValue())
164.
165. // + " in " + this + ": " + cs);
166.
167. mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
168.
169. }
170.
171. }
172.
173. }
174.
175. }
176.
177.
178.
179. return dr;
180.
181. }
使用Drawable一般情况下效率较高,且不易发生内存泄露。

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

BitMapFactory.java

1. /**
2.
3. * Decode an input stream into a bitmap. If the input stream is null, or
4.
5. * cannot be used to decode a bitmap, the function returns null.
6.
7. * The stream's position will be where ever it was after the encoded data
8.
9. * was read.
10.
11. *
12.
13. * @param is The input stream that holds the raw data to be decoded into a
14.
15. * bitmap.
16.
17. * @param outPadding If not null, return the padding rect for the bitmap if
18.
19. * it exists, otherwise set padding to [-1,-1,-1,-1]. If
20.
21. * no bitmap is returned (null) then padding is
22.
23. * unchanged.
24.
25. * @param opts null-ok; Options that control downsampling and whether the
26.
27. * image should be completely decoded, or just is size returned.
28.
29. * @return The decoded bitmap, or null if the image data could not be
30.
31. * decoded, or, if opts is non-null, if opts requested only the
32.
33. * size be returned (in opts.outWidth and opts.outHeight)
34.
35. */
36.
37. public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
38.
39. // we don't throw in this case, thus allowing the caller to only check
40.
41. // the cache, and not force the image to be decoded.
42.
43. if (is == null) {
44.
45. return null;
46.
47. }
48.
49.
50.
51. // we need mark/reset to work properly
52.
53.
54.
55. if (!is.markSupported()) {
56.
57. is = new BufferedInputStream(is, 16 * 1024);
58.
59. }
60.
61.
62.
63. // so we can call reset() if a given codec gives up after reading up to
64.
65. // this many bytes. FIXME: need to find out from the codecs what this
66.
67. // value should be.
68.
69. is.mark(1024);
70.
71.
72.
73. Bitmap bm;
74.
75.
76.
77. if (is instanceof AssetManager.AssetInputStream) {
78.
79. bm = nativeDecodeAsset(((AssetManager.AssetInputStream) is).getAssetInt(),
80.
81. outPadding, opts);
82.
83. } else {
84.
85. // pass some temp storage down to the native code. 1024 is made up,
86.
87. // but should be large enough to avoid too many small calls back
88.
89. // into is.read(...) This number is not related to the value passed
90.
91. // to mark(...) above.
92.
93. byte [] tempStorage = null;
94.
95. if (opts != null)
96.
97. tempStorage = opts.inTempStorage;
98.
99. if (tempStorage == null)
100.
101. tempStorage = new byte[16 * 1024];
102.
103. bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
104.
105. }
106.
107.
108.
109. return finishDecode(bm, outPadding, opts);
110.
111. }
我们每次调用BitMapFactory中的生产bitmap的方法的时候都会new一个bitmap出来,为了避免内存溢出,我们有两种主要的思路:
1. 使用缓存,避免重复new同一个图片
2. 销毁bitmap,使用完之后立刻销毁bitmap
缓存需要自己实现,如果是销毁的话,可以使用Bitmap中的recycle()方法。

摘自 ZillaPress
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值