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