2012-03-19 12 views
6

私はRunnable秒で約プレーしてきたし、次にあなたが同じことを行うが、HandlerRunnableを投稿ただしならば、コールバックを削除し、コールバックが動作しませんん削除ViewにあなたがpostDelayedRunnable場合ということを発見しました作業。ビューとハンドラの実行可能ファイルの転記と取り消しが異なる理由は何ですか?

この作品( Runnableラン()のコードが実行されることは決してありません)んなぜ

これがそうであるよう( Runnableラン()のコードは常に実行されます)ではない
Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     // execute some code 
    } 
}; 

Handler handler = new Handler(); 
handler.postDelayed(runnable, 10000); 
handler.removeCallbacks(runnable); 

?:

Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     // execute some code 
    } 
}; 

View view = findViewById(R.id.some_view); 
view.postDelayed(runnable, 10000); 
view.removeCallbacks(runnable); 
+1

あなたが行ったことがあります使用しないでよ? – CommonsWare

+0

私はこれを見ていませんでしたが、これがどのように役立つのか説明できますか?私はドキュメントを読んだが、これが私の上記のViewの例でどのように役立つのかわかりません。 – Martyn

+2

'View.removeCallbacks()'は常にtrueを返します(少なくともICSでも残ります)[こちらを参照](http://grepcode.com/file/repository.grepcode.com/java/ext/) com.google.android/android/4.0.3_r1/android/view/View.java#8786) – zapl

答えて

4

Viewがウィンドウに接続されていない場合は、Androidでのバグのように見えます。したがって、タイミングに問題がある可能性があります。がウィンドウに接続されるまで、Runnableを投稿または削除しないようにしてください。

この問題を再現するサンプルプロジェクトがあるとしたら、それを見てみたいと思います。さもなければ、私は自分で作ろうと思うので、私が想定しているバグを報告するのに使うことができるものがあります。


UPDATE

コメントで述べたように、より一般的なウィジェットの動作にremoveCallbacks()ので、これはOPのサンプル・コードごとに、WebView固有の問題で表示されます。

+0

https://github.com/martynhaigh/RunnableCancelTest – Martyn

+0

@Martyn:うん、私の疑いがあったように、 'WebView'はウィンドウに付いていませんその時点で(例えば、 'getWindowToken()'が 'null'を返します)、あなたはAndroidでこのバグを旅しようとしています。私は早急に問題を提出します。その間、確実に 'removeCallbacks()'に 'Handler'を使う必要があります。 – CommonsWare

+0

@Martyn:問題は私が思ったよりも微妙だと思われる。 'Button'を使って問題を再現しようとしましたが、' postDelayed() 'の時に' Button'がウィンドウに付けられていなくても 'removeCallbacks()'は成功します。私は今あなたの難しさが「WebView」に特有かもしれないと推測しています。それにもかかわらず、おそらくあなたはたぶん 'Handler'を使うべきでしょう。 – CommonsWare

0

さまざまな理由から、アニメーションを開始するときに、Viewのハンドラ(view.getHandler())が準備できていない可能性があります。

そのため、実行可能ファイルをビューに割り当てる前に待つ必要があります。

ViewRootImpl.javaを見ると
private void assignRunnable(final View view, final Runnable runnable, final int delay) 
{ 
    if (view.getHandler() == null) { 
    // View is not ready, postpone assignment 
    this.getView().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
     assignRunnable(view, runnable, delay); 
     } 
    }, 100); 

    //Abort 
    return; 
    } 

    //View is ready, assign the runnable 
    view.postDelayed(runnable, delay); 
} 
0

、View.removeCallbacksの意味:あなたは活動の中から、ここで実行可能を投稿する前に利用できるようにハンドラを待っコードであることをやろうとしていると仮定すると、

()はあまり言わないように思われます。

RunQueue.removeCallbacksは、ArrayListからRunnablesを削除するだけです。 hereを参照してください。

removeCallbacksの前にRunQueue.executeActionsが呼び出された場合、ArrayListはすべての場合にクリアされ、removeCallbacksはノーオペレーションになります。 hereを参照してください。

RunQueue.executeActionsは、トラバーサルごとに呼び出されます。hereを参照してください。

私が何かを見逃していない限り、View.postを呼んだ後にトラバーサルが発生した場合、View.removeCallbacksは動作しません。

私は上記の@ジェームズ・ワルドコメントに固執し、 `removeCallbacks()`からの戻り値をチェックView.post

関連する問題