Message.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.os; 18 19import android.os.Bundle; 20import android.os.Parcel; 21import android.os.Parcelable; 22 23/** 24 * 25 * Defines a message containing a description and arbitrary data object that can be 26 * sent to a {@link Handler}. This object contains two extra int fields and an 27 * extra object field that allow you to not do allocations in many cases. 28 * 29 * <p class="note">While the constructor of Message is public, the best way to get 30 * one of these is to call {@link #obtain Message.obtain()} or one of the 31 * {@link Handler#obtainMessage Handler.obtainMessage()} methods, which will pull 32 * them from a pool of recycled objects.</p> 33 */ 34public final class Message implements Parcelable { 35 /** 36 * User-defined message code so that the recipient can identify 37 * what this message is about. Each {@link Handler} has its own name-space 38 * for message codes, so you do not need to worry about yours conflicting 39 * with other handlers. 40 */ 41 public int what; 42 43 // Use these fields instead of using the class's Bundle if you can. 44 /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()} 45 if you only need to store a few integer values. */ 46 public int arg1; 47 48 /** arg1 and arg2 are lower-cost alternatives to using {@link #setData(Bundle) setData()} 49 if you only need to store a few integer values.*/ 50 public int arg2; 51 52 /** An arbitrary object to send to the recipient. This must be null when 53 * sending messages across processes. */ 54 public Object obj; 55 56 /** Optional Messenger where replies to this message can be sent. 57 */ 58 public Messenger replyTo; 59 60 /*package*/ long when; 61 62 /*package*/ Bundle data; 63 64 /*package*/ Handler target; 65 66 /*package*/ Runnable callback; 67 68 // sometimes we store linked lists of these things 69 /*package*/ Message next; 70 71 private static Object mPoolSync = new Object(); 72 private static Message mPool; 73 private static int mPoolSize = 0; 74 75 private static final int MAX_POOL_SIZE = 10; 76 77 /** 78 * Return a new Message instance from the global pool. Allows us to 79 * avoid allocating new objects in many cases. 80 */ 81 public static Message obtain() { 82 synchronized (mPoolSync) { 83 if (mPool != null) { 84 Message m = mPool; 85 mPool = m.next; 86 m.next = null; 87 return m; 88 } 89 } 90 return new Message(); 91 } 92 93 /** 94 * Same as {@link #obtain()}, but copies the values of an existing 95 * message (including its target) into the new one. 96 * @param orig Original message to copy. 97 * @return A Message object from the global pool. 98 */ 99 public static Message obtain(Message orig) { 100 Message m = obtain(); 101 m.what = orig.what; 102 m.arg1 = orig.arg1; 103 m.arg2 = orig.arg2; 104 m.obj = orig.obj; 105 m.replyTo = orig.replyTo; 106 if (orig.data != null) { 107 m.data = new Bundle(orig.data); 108 } 109 m.target = orig.target; 110 m.callback = orig.callback; 111 112 return m; 113 } 114 115 /** 116 * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned. 117 * @param h Handler to assign to the returned Message object's <em>target</em> member. 118 * @return A Message object from the global pool. 119 */ 120 public static Message obtain(Handler h) { 121 Message m = obtain(); 122 m.target = h; 123 124 return m; 125 } 126 127 /** 128 * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on 129 * the Message that is returned. 130 * @param h Handler to assign to the returned Message object's <em>target</em> member. 131 * @param callback Runnable that will execute when the message is handled. 132 * @return A Message object from the global pool. 133 */ 134 public static Message obtain(Handler h, Runnable callback) { 135 Message m = obtain(); 136 m.target = h; 137 m.callback = callback; 138 139 return m; 140 } 141 142 /** 143 * Same as {@link #obtain()}, but sets the values for both <em>target</em> and 144 * <em>what</em> members on the Message. 145 * @param h Value to assign to the <em>target</em> member. 146 * @param what Value to assign to the <em>what</em> member. 147 * @return A Message object from the global pool. 148 */ 149 public static Message obtain(Handler h, int what) { 150 Message m = obtain(); 151 m.target = h; 152 m.what = what; 153 154 return m; 155 } 156 157 /** 158 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, and <em>obj</em> 159 * members. 160 * @param h The <em>target</em> value to set. 161 * @param what The <em>what</em> value to set. 162 * @param obj The <em>object</em> method to set. 163 * @return A Message object from the global pool. 164 */ 165 public static Message obtain(Handler h, int what, Object obj) { 166 Message m = obtain(); 167 m.target = h; 168 m.what = what; 169 m.obj = obj; 170 171 return m; 172 } 173 174 /** 175 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 176 * <em>arg1</em>, and <em>arg2</em> members. 177 * 178 * @param h The <em>target</em> value to set. 179 * @param what The <em>what</em> value to set. 180 * @param arg1 The <em>arg1</em> value to set. 181 * @param arg2 The <em>arg2</em> value to set. 182 * @return A Message object from the global pool. 183 */ 184 public static Message obtain(Handler h, int what, int arg1, int arg2) { 185 Message m = obtain(); 186 m.target = h; 187 m.what = what; 188 m.arg1 = arg1; 189 m.arg2 = arg2; 190 191 return m; 192 } 193 194 /** 195 * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 196 * <em>arg1</em>, <em>arg2</em>, and <em>obj</em> members. 197 * 198 * @param h The <em>target</em> value to set. 199 * @param what The <em>what</em> value to set. 200 * @param arg1 The <em>arg1</em> value to set. 201 * @param arg2 The <em>arg2</em> value to set. 202 * @param obj The <em>obj</em> value to set. 203 * @return A Message object from the global pool. 204 */ 205 public static Message obtain(Handler h, int what, 206 int arg1, int arg2, Object obj) { 207 Message m = obtain(); 208 m.target = h; 209 m.what = what; 210 m.arg1 = arg1; 211 m.arg2 = arg2; 212 m.obj = obj; 213 214 return m; 215 } 216 217 /** 218 * Return a Message instance to the global pool. You MUST NOT touch 219 * the Message after calling this function -- it has effectively been 220 * freed. 221 */ 222 public void recycle() { 223 synchronized (mPoolSync) { 224 if (mPoolSize < MAX_POOL_SIZE) { 225 clearForRecycle(); 226 227 next = mPool; 228 mPool = this; 229 } 230 } 231 } 232 233 /** 234 * Make this message like o. Performs a shallow copy of the data field. 235 * Does not copy the linked list fields, nor the timestamp or 236 * target/callback of the original message. 237 */ 238 public void copyFrom(Message o) { 239 this.what = o.what; 240 this.arg1 = o.arg1; 241 this.arg2 = o.arg2; 242 this.obj = o.obj; 243 this.replyTo = o.replyTo; 244 245 if (o.data != null) { 246 this.data = (Bundle) o.data.clone(); 247 } else { 248 this.data = null; 249 } 250 } 251 252 /** 253 * Return the targeted delivery time of this message, in milliseconds. 254 */ 255 public long getWhen() { 256 return when; 257 } 258 259 public void setTarget(Handler target) { 260 this.target = target; 261 } 262 263 /** 264 * Retrieve the a {@link android.os.Handler Handler} implementation that 265 * will receive this message. The object must implement 266 * {@link android.os.Handler#handleMessage(android.os.Message) 267 * Handler.handleMessage()}. Each Handler has its own name-space for 268 * message codes, so you do not need to 269 * worry about yours conflicting with other handlers. 270 */ 271 public Handler getTarget() { 272 return target; 273 } 274 275 /** 276 * Retrieve callback object that will execute when this message is handled. 277 * This object must implement Runnable. This is called by 278 * the <em>target</em> {@link Handler} that is receiving this Message to 279 * dispatch it. If 280 * not set, the message will be dispatched to the receiving Handler's 281 * {@link Handler#handleMessage(Message Handler.handleMessage())}. */ 282 public Runnable getCallback() { 283 return callback; 284 } 285 286 /** 287 * Obtains a Bundle of arbitrary data associated with this 288 * event, lazily creating it if necessary. Set this value by calling {@link #setData(Bundle)}. 289 */ 290 public Bundle getData() { 291 if (data == null) { 292 data = new Bundle(); 293 } 294 295 return data; 296 } 297 298 /** 299 * Like getData(), but does not lazily create the Bundle. A null 300 * is returned if the Bundle does not already exist. 301 */ 302 public Bundle peekData() { 303 return data; 304 } 305 306 /** Sets a Bundle of arbitrary data values. Use arg1 and arg1 members 307 * as a lower cost way to send a few simple integer values, if you can. */ 308 public void setData(Bundle data) { 309 this.data = data; 310 } 311 312 /** 313 * Sends this Message to the Handler specified by {@link #getTarget}. 314 * Throws a null pointer exception if this field has not been set. 315 */ 316 public void sendToTarget() { 317 target.sendMessage(this); 318 } 319 320 /*package*/ void clearForRecycle() { 321 what = 0; 322 arg1 = 0; 323 arg2 = 0; 324 obj = null; 325 replyTo = null; 326 when = 0; 327 target = null; 328 callback = null; 329 data = null; 330 } 331 332 /** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}). 333 */ 334 public Message() { 335 } 336 337 public String toString() { 338 StringBuilder b = new StringBuilder(); 339 340 b.append("{ what="); 341 b.append(what); 342 343 b.append(" when="); 344 b.append(when); 345 346 if (arg1 != 0) { 347 b.append(" arg1="); 348 b.append(arg1); 349 } 350 351 if (arg2 != 0) { 352 b.append(" arg2="); 353 b.append(arg2); 354 } 355 356 if (obj != null) { 357 b.append(" obj="); 358 b.append(obj); 359 } 360 361 b.append(" }"); 362 363 return b.toString(); 364 } 365 366 public static final Parcelable.Creator<Message> CREATOR 367 = new Parcelable.Creator<Message>() { 368 public Message createFromParcel(Parcel source) { 369 Message msg = Message.obtain(); 370 msg.readFromParcel(source); 371 return msg; 372 } 373 374 public Message[] newArray(int size) { 375 return new Message[size]; 376 } 377 }; 378 379 public int describeContents() { 380 return 0; 381 } 382 383 public void writeToParcel(Parcel dest, int flags) { 384 if (obj != null || callback != null) { 385 throw new RuntimeException( 386 "Can't marshal objects across processes."); 387 } 388 dest.writeInt(what); 389 dest.writeInt(arg1); 390 dest.writeInt(arg2); 391 dest.writeLong(when); 392 dest.writeBundle(data); 393 Messenger.writeMessengerOrNullToParcel(replyTo, dest); 394 } 395 396 private final void readFromParcel(Parcel source) { 397 what = source.readInt(); 398 arg1 = source.readInt(); 399 arg2 = source.readInt(); 400 when = source.readLong(); 401 data = source.readBundle(); 402 replyTo = Messenger.readMessengerOrNullFromParcel(source); 403 } 404} 405 406