0

私は今アンドロイドプロジェクトをやっています。スレッドに問題があります。ホームボタンが押されたときにスレッドを一時停止し、アプリに戻ったときにスレッドを再開したい。

これは私のコードです:

Handler handler = new Handler() 
{
    @Override
    public void handleMessage(Message msg) 
    {
        int tempWaktu = (Integer) msg.obj;

        if(!status){
            if(tempWaktu < 10 ) textSec.setText("0"+tempWaktu);
            else textSec.setText(""+tempWaktu);
        }

        if(tempWaktu==0){
            stopYourActivity();
        }
    }
}; //handler

@Override
public void onStart() 
{
    super.onStart();

    timer = new Thread(new Runnable() {
        public void run() {
        try 
        {
            while(jalan){
                if(running){
                    Thread.sleep(1000);
                    waktu--;
                    Message msg = handler.obtainMessage(1, waktu);
                    handler.sendMessage(msg);
                    if(waktu==0){
                        running = false;
                    }
                }
            }
        } 
        catch (Throwable t){

        }
    }//run
    });//background
    timer.start();
}//onStart


@Override
public void onPause(){
    synchronized (timer) {
        try {
            timer.wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    pause = true;
}

@Override
public void onResume(){
    super.onResume();
    if(pause){
        synchronized (timer) {
            timer.notify(); textSec.postInvalidate();
            pause = false;
        } 
    }
}

ホームボタンを押してもスレッドが停止せず、アプリに戻るとUIがフリーズします。理由がわかりません。

私が必要とするのは、ホームボタンを押したときにスレッドが一時停止し、実行中のスレッドを元に戻し、UI がフリーズしないことです。

私を助けるためにあなたが書いたコードに感謝します。どうもありがとうございます。


アップデート

私はこのようにtimer.wait()中に入れrun()ました:

@Override
public void onStart() 
{
    super.onStart();

    if(!pause){
        timer = new Thread(new Runnable() {
            public void run() {
            try 
            {
                while(jalan){
                    if(running){
                        Thread.sleep(1000);
                        waktu--;
                        Message msg = handler.obtainMessage(1, waktu);
                        handler.sendMessage(msg);
                        Log.v("Timer Thread", "Thread Berjalan "+waktu);
                        if(waktu==0){
                            Log.v("Thread Timer", "Waktu Berhenti");
                            running = false;
                        }
                        if(pause){
                            synchronized (timer) {
                                timer.wait();
                            }
                        }
                    }
                }
            } 
            catch (Throwable t){    
            }
        }//run
        });//background
        timer.start();
    }

}//onStart

上記のようtimer.notify()onResume()なり、ホームを押すと強制的に閉じます。ログには次のように書かれています:

07-19 10:27:41.173: E/AndroidRuntime(2280): FATAL EXCEPTION: main
07-19 10:27:41.173: E/AndroidRuntime(2280): android.app.SuperNotCalledException: Activity {com.konsep.baby.scratch/com.konsep.baby.scratch.BabyScratchChallenge} did not call through to super.onPause()
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.Activity.performPause(Activity.java:3854)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1191)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2341)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2311)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2291)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.access$1700(ActivityThread.java:117)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:938)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.os.Handler.dispatchMessage(Handler.java:99)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.os.Looper.loop(Looper.java:123)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at android.app.ActivityThread.main(ActivityThread.java:3683)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at java.lang.reflect.Method.invokeNative(Native Method)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at java.lang.reflect.Method.invoke(Method.java:507)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
07-19 10:27:41.173: E/AndroidRuntime(2280):     at dalvik.system.NativeStart.main(Native Method)

私のコードの何が問題なのですか?

4

2 に答える 2

1

最初の問題は、 のライフサイクルがActivity実際にどのように機能するかです。ホーム画面に移動すると、電流Activityが停止状態になります (つまりonStop()、呼び出されます)。したがって、アプリケーションに戻ると、onStart()thenが表示されonResume()ます。それでは、その情報に基づいてコードで何が起こるかを調べてみましょう。

  1. 最初の起動時に、新しいスレッドが作成されonStart()て開始されます。 onResume()ブール値フラグのために何もしません。
  2. HOMEボタンを押すonPause()と呼び出され、このスレッドでwait()が呼び出されます
  3. アプリケーションに戻り、onStart()が呼び出され、タイマーが新しいスレッドを指し、古いスレッドがぶら下がったままになります。
  4. onResume()が呼び出さnotify()れ、新しい Thread インスタンスに送信されます。

したがって、ここでの問題は、Thread youwait()と thread younotify()が同じオブジェクトではないということです。

2番目の問題は、wait()実際に何をするかです。Java ドキュメントから (強調を追加):

別のスレッドがこのオブジェクトの notify() または notifyAll() メソッドを呼び出すまで、呼び出しスレッドを待機させます。このメソッドは、このオブジェクトのモニターを所有するスレッドによってのみ呼び出すことができます。スレッドがモニターの所有者になる方法については、notify() を参照してください。

を呼び出しwait()てもThread、作成された はブロックされず、メソッドThreadを呼び出したスレッド(この場合はメイン スレッド) がブロックされます。したがって、一時停止中にメインスレッドを正常にブロックし、ロックを解除する方法がないため、フリーズするアプリケーションを作成しました。

バックグラウンド スレッドを使用wait()して一時停止する場合は、バックグラウンド スレッド内 (つまり、ブロック内)から呼び出されるnotify()ようにする必要があります。wait()run()

于 2012-07-19T03:04:24.597 に答える
0

Google のトレーニング ページで既に説明されています。ここ

アプリが一時停止すると、「CPU を消費する可能性のあるアニメーションまたはその他の進行中のアクションを停止します」。

于 2012-07-19T02:41:57.863 に答える