web-dev-qa-db-ja.com

removeCallbacksが実行可能を停止しない

私はメソッドから呼び出しています:

myHandler.postDelayed(mMyRunnableHide, 6000);

どの呼び出し:

public Runnable mMyRunnableHide = new Runnable()
{

    public void run()
    {
        mTextDisplay.setText("");
        DisplayX();
    }
 };

画面上のボタンがクリックされた場合、ランナブルを停止したい:

   Button next = (Button) findViewById(R.id.Breaction);
    next.setOnClickListener(new View.OnClickListener() {
        public void onClick(View view) {

            myHandler.removeCallbacks(mMyRunnableHide);

            mTextDisplay.setText("");
            DisplayX();
            }
        });   
    }

removecallbacksはランナブルを停止していません。何が悪いのですか?正しい方法を使用していますか?ユーザーがボタンをクリックしたときにランナブルを「実行しない」にしたいだけです。

助けてくれてありがとう。

38
codemanusa

removeCallbacks(..)pendingメッセージ(Runnables)のみを停止するように見えます。ランナブルがすでに開始されている場合、それを停止することはできません(少なくともこの方法では)。

または、Runnableクラスを拡張して、次のようなある種の終了スイッチを与えることもできます。

public class MyRunnable implements Runnable
{
   private boolean killMe = false;

   private void run()
   {
      if(killMe)
         return;

      /* do your work */
   }

   private void killRunnable()
   {
      killMe = true;
   }
}

これは起動を妨げるだけですが、時々killMeをチェックして救済することができます。 (何らかのバックグラウンドスレッドのような)ランナブルをループしている場合は、次のように言うことができます。

while(!killMe) {
   /* do work */
}

お役に立てれば

[〜#〜] edit [〜#〜]これに関するアップデートを投稿したかっただけです。この最初の投稿以来、Googleはこのすべてのものを処理するAsyncTaskと呼ばれる素晴らしいクラスを考え出しました。これは物事の正しい方法であるため、これを読んでいる人は誰でも実際にそれを調べる必要があります。

あなたはそれについて読むことができます ここ

36
mtmurdock

Handler.removeCallbackは同期的であり、うまく機能します:

  1. postDelayedは常にメインスレッドで呼び出します。
  2. あなたは常にメインスレッドでremoveCallbackを呼び出します
  3. コールバックを削除した後は、再度postDelayedを呼び出さないでください。

したがって、あなたの場合、removeCallbacksは、メインスレッドで実行されるボタンハンドラーから呼び出されます。ただし、コードでpostDelayedを呼び出す場所を示していません。バックグラウンドスレッドから呼び出すと、問題が発生します。

これらのメソッドをバックグラウンドスレッドから呼び出さないことが確実で、呼び出しの順序が正しい場合、構成の変更(画面の回転など)でアクティビティが再作成されるため、キャンセルされていないタスクが意図せずに残っ​​ている可能性があります。この種の問題を防ぐために、必ずremoveCallbacksメソッドでonDestroyを再度呼び出すようにしてください。

13
Mister Smith

Mtmurdockが説明していることを実現する別の方法を次に示します。このクラスでは、Runnableが匿名の内部クラスとして定義されているクラスのインスタンス変数を編集できます。

package support;

/**
* Runnable that can be stopped from executing
*/
public abstract class KillableRunnable implements Runnable{

private boolean isKilled=false;

/**
 * Instead of Overriding run(), override this method to perform a Runnable operation. 
 * This will allow editing instance variables in the class that this Runnable is defined
 */
public abstract void doWork();

//The handler that posts this Runnable will call this method. 
//By default, check if it has been killed. doWork() will now be the method 
//override to implement this Runnable
@Override
final public void run(){
    if(!isKilled){
        doWork();
    }
}

final public void kill(){
    isKilled=true;
}
}
7
James L.

RemoveCallbacks(..)が保留中のメッセージ(Runnables)を停止するだけだとは思わない、removeCallbacks(..)が機能しない原因は他にもあると思いますが、わかりません。 postDelayed(..)とremoveCallbacks(..)が同じスレッドにあるため

0
xiangyu shi