107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko/*
207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * Copyright (C) 2015 The Android Open Source Project
307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko *
407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * Licensed under the Apache License, Version 2.0 (the "License");
507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * you may not use this file except in compliance with the License.
607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * You may obtain a copy of the License at
707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko *
807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko *      http://www.apache.org/licenses/LICENSE-2.0
907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko *
1007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * Unless required by applicable law or agreed to in writing, software
1107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * distributed under the License is distributed on an "AS IS" BASIS,
1207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * See the License for the specific language governing permissions and
1407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * limitations under the License
1507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko */
1607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
1707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkopackage com.android.tv.common;
1807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
1907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport android.os.Handler;
2007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport android.os.Looper;
2107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport android.os.Message;
2207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport android.support.annotation.NonNull;
2307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
2407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkoimport java.lang.ref.WeakReference;
2507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
2607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko/**
2707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * A Handler that keeps a {@link WeakReference} to an object.
2807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko *
2907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * <p>Use this to prevent leaking an Activity or other Context while messages are still pending.
3007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * When you extend this class you <strong>MUST NOT</strong> use a non static inner class, or the
3107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * containing object will still be leaked.
3207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko *
3307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * <p>See <a href="http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html">
3407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko * Avoiding memory leaks</a>.
3507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko */
3607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalkopublic abstract class WeakHandler<T> extends Handler {
3707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    private final WeakReference<T> mRef;
3807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
3907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    /**
4007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * Constructs a new  handler with a weak reference to the given referent using the provided
4107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * Looper instead of the default one.
4207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     *
4307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * @param looper The looper, must not be null.
4407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * @param ref the referent to track
4507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     */
4607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    public WeakHandler(@NonNull Looper looper, T ref) {
4707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        super(looper);
4807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        mRef = new WeakReference<>(ref);
4907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    }
5007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
5107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    /**
5207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * Constructs a new handler with a weak reference to the given referent.
5307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     *
5407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * @param ref the referent to track
5507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     */
5607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    public WeakHandler(T ref) {
5707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        mRef = new WeakReference<>(ref);
5807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    }
5907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
6007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    /**
6107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * Calls {@link #handleMessage(Message, Object)} if the WeakReference is not cleared.
6207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     */
6307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    @Override
6407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    public final void handleMessage(Message msg) {
6507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        T referent = mRef.get();
6607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        if (referent == null) {
6707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko            return;
6807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        }
6907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko        handleMessage(msg, referent);
7007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    }
7107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko
7207b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    /**
7307b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * Subclasses must implement this to receive messages.
7407b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     *
7507b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * <p>If the WeakReference is cleared this method will no longer be called.
7607b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     *
7707b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * @param msg      the message to handle
7807b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     * @param referent the referent. Guaranteed to be non null.
7907b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko     */
8007b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko    protected abstract void handleMessage(Message msg, @NonNull T referent);
8107b043dc3db83d6d20f0e8513b946830ab00e37bNick Chalko}
82