web-dev-qa-db-ja.com

ハンドラーからすべてのコールバックを削除する方法は?

メイン Activity によって呼び出されたサブアクティビティから Handler があります。このハンドラーは、サブクラスによって postDelay Runnableの一部として使用され、それらを管理できません。さて、onStopイベントで、アクティビティを完了する前にそれらを削除する必要があります(どういうわけかfinish()を呼び出しましたが、それでも何度も呼び出します)。ハンドラーからすべてのコールバックを削除する方法はありますか?

203
Luke Vo

私の経験では、これを呼び出すことはうまくいきました!

handler.removeCallbacksAndMessages(null);

RemoveCallbacksAndMessagesのドキュメントには、次のように書かれています...

Objがトークンであるコールバックおよび送信済みメッセージの保留中の投稿を削除します。 トークンがnullの場合、すべてのコールバックとメッセージが削除されます。

479
josh527

特定のRunnablename__インスタンスについては、Handler.removeCallbacks()を呼び出します。 Runnablename__インスタンス自体を使用して登録解除するコールバックを決定するため、投稿が作成されるたびに新しいインスタンスを作成する場合は、キャンセルするために正確なRunnablename__への参照があることを確認する必要があります。例:

Handler myHandler = new Handler();
Runnable myRunnable = new Runnable() {
    public void run() {
        //Some interesting task
    }
};

myHandler.postDelayed(myRunnable, x)を呼び出して、コード内の他の場所のメッセージキューに別のコールバックを投稿し、myHandler.removeCallbacks(myRunnable)を使用して保留中のコールバックをすべて削除できます。

残念ながら、MessageQueuename__のHandlername__オブジェクトをリクエストしても、アイテムを追加および削除するメソッドはパッケージで保護されているため、MessageQueuename__全体を単純に「クリア」することはできません(Android.osパッケージ内のクラスのみが呼び出すことができます)それら)。薄いHandlername__サブクラスを作成して、Runnablename__sのリストを管理する必要があります。または、各Activityname__間でメッセージを渡すための別のパラダイムを見てください

お役に立てば幸いです!

18
Devunwired

Runnable参照がない場合、最初のコールバックでメッセージのobjを取得し、 removeCallbacksAndMessages() を使用して、関連するすべてのコールバックを削除します。

8
alphazero

新しいハンドラーと実行可能ファイルを定義します。

private Handler handler = new Handler(Looper.getMainLooper());
private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // Do what ever you want
        }
    };

コールポストの遅延:

handler.postDelayed(runnable, sleep_time);

ハンドラーからコールバックを削除します。

handler.removeCallbacks(runnable);
5
savepopulation

実際、ここには少し重要なポイントがあります。 HandlerRunnableを最初に定義する必要があります。実際、removeCallbacks(runnable)は正しく機能しますが、毎回定義する場合、それらを処理できない場合があります。

間違った方法:

    public class FooActivity extends Activity {
           private void handleSomething(){
                Handler handler = new Handler();
                Runnable runnable = new Runnable() {
                   @Override
                   public void run() {
                      doIt();
                  }
               };
              if(shouldIDoIt){
                  //doIt() works after 3 seconds.
                  handler.postDelayed(runnable, 3000);
              } else {
                  handler.removeCallbacks(runnable);
              }
           }

          public void onClick(View v){
              handleSomething();
          }
    } 

onClick(..)メソッドを呼び出す場合、呼び出す前にdoIt()メソッドの呼び出しを停止することはありません。毎回new Handlerおよびnew Runnableインスタンスを作成するためです。このようにして、handlerおよびrunnableに属する必要な参照を失いました。インスタンス。

本当の方法:

 public class FooActivity extends Activity {
        Handler handler = new Handler();
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                doIt();
            }
        };
        private void handleSomething(){
            if(shouldIDoIt){
                //doIt() works after 3 seconds.
                handler.postDelayed(runnable, 3000);
            } else {
                handler.removeCallbacks(runnable);
            }
       }

       public void onClick(View v){
           handleSomething();
       }
 } 

このようにして、実際の参照を失うことはなく、removeCallbacks(runnable)は正常に機能します。

重要な文は、「使用するものでActivityまたはFragmentでグローバルとして定義する」です。

2
oguzhan

josh527が言ったように、handler.removeCallbacksAndMessages(null);は機能します。
しかし、なぜ?
ソースコードを見ると、より明確に理解できます。ハンドラー(コールバック)からコールバック/メッセージを削除するには、3つのタイプのメソッドがあります。

  1. コールバック(およびトークン)で削除
  2. message.what(およびトークン)で削除します
  3. トークンで削除

Handler.Java(オーバーロードメソッドを残す)

/**
 * Remove any pending posts of Runnable <var>r</var> with Object
 * <var>token</var> that are in the message queue.  If <var>token</var> is null,
 * all callbacks will be removed.
 */
public final void removeCallbacks(Runnable r, Object token)
{
    mQueue.removeMessages(this, r, token);
}

/**
 * Remove any pending posts of messages with code 'what' and whose obj is
 * 'object' that are in the message queue.  If <var>object</var> is null,
 * all messages will be removed.
 */
public final void removeMessages(int what, Object object) {
    mQueue.removeMessages(this, what, object);
}

/**
 * Remove any pending posts of callbacks and sent messages whose
 * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
 * all callbacks and messages will be removed.
 */
public final void removeCallbacksAndMessages(Object token) {
    mQueue.removeCallbacksAndMessages(this, token);
}

MessageQueue.Javaは実際の作業を行います。

void removeMessages(Handler h, int what, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h && p.what == what
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.what == what
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

void removeMessages(Handler h, Runnable r, Object object) {
    if (h == null || r == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h && p.callback == r
               && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && n.callback == r
                    && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}

void removeCallbacksAndMessages(Handler h, Object object) {
    if (h == null) {
        return;
    }

    synchronized (this) {
        Message p = mMessages;

        // Remove all messages at front.
        while (p != null && p.target == h
                && (object == null || p.obj == object)) {
            Message n = p.next;
            mMessages = n;
            p.recycleUnchecked();
            p = n;
        }

        // Remove all messages after front.
        while (p != null) {
            Message n = p.next;
            if (n != null) {
                if (n.target == h && (object == null || n.obj == object)) {
                    Message nn = n.next;
                    n.recycleUnchecked();
                    p.next = nn;
                    continue;
                }
            }
            p = n;
        }
    }
}
1
JamesRobert