2014-02-24 12 views
12

In letzter Zeit sah ich http://developer.android.com/reference/android/os/CountDownTimer.html und fragte mich, ob es eine entsprechende Klasse für Stoppuhren gibt, da ich dem Benutzer meiner App sagen möchte, wie lange er bereits versucht, das Puzzle zu lösen. Ich meine, es ist nicht so kompliziert, eine solche Stoppuhr selbst zu programmieren. Ich habe versucht, so etwas wieGibt es bereits eine StopWatch-Klasse für Android und warum funktioniert meine Implementierung nicht?

Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      while (true) { 
       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
       } 
       long seconds = (System.currentTimeMillis() - t)/1000; 
       statusBar.setText(String.format("%02d:%02d", seconds/60, seconds % 60)); 
      } 
     } 

    }; 
    statusBar.post(runnable); 

Aber bizarr das Layout meiner Tätigkeit aufgeblasen wird nicht mehr, da ich diese statusBar.post(runnable); am Ende des onCreate Methode des acitivity habe was bedeutet, dass die App nach dem Start nur ich einen weißen Bildschirm statt die normale gui.

+0

, das Richtige zu tun, ist mit einem Timer zu starten. – Merlevede

+0

Sie können den Hauptthread nicht schlafen. Und wenn Sie diesen Code in einem anderen Thread ausführen, benötigen Sie einen Handler, um in die Benutzeroberfläche zu schreiben (nur der Hauptthread kann die Benutzeroberfläche ändern). –

Antwort

6

Sie sollten einen Chronometer verwenden.

Wie auch immer, Ihr Code kann funktionieren, wenn Sie den Ruhezustand vom UI-Thread entfernen.

private final Runnable mRunnable = new Runnable() { 
    @Override 
    public void run() { 
     if (mStarted) { 
      long seconds = (System.currentTimeMillis() - t)/1000; 
      statusBar.setText(String.format("%02d:%02d", seconds/60, seconds % 60)); 
      handler.postDelayed(runnable, 1000L); 
     } 
    } 

}; 

private Hanlder mHandler; 
private boolean mStarted; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    mHandler = new Handler(); 
} 

@Override 
protected void onStart() { 
    super.onStart(); 
    mStarted = true; 
    mHandler.postDealyed(runnable, 1000L); 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
    mStarted = false; 
    mHandler.removeCallbacks(mRunnable); 
} 
+0

@Ammaraly nur OP weiß, ich habe seinen Code in erster Linie geändert. –

1

Warum Ihr Code nicht funktioniert, liegt daran, dass Sie einen Runnable in die Nachrichtenwarteschlange des UI-Threads eingeben. Das ausführbare Runnable wird für immer in der while-Schleife ausgeführt, wodurch verhindert wird, dass der UI-Thread andere Aufgaben ausführt, z. B. das Zeichnen Ihres Layouts und das Reagieren auf Eingaben.

Verwenden Thread.sleep() in einem UI-Thread ist fast immer falsch. Verwenden Sie stattdessen eine Timer.

16

Werfen Sie einen Blick auf die Chronometer Klasse.

Beispielcode aus APIDemo:

import android.app.Activity; 
import android.os.Bundle; 
import android.os.SystemClock; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.Chronometer; 

public class ChronometerDemo extends Activity { 
    Chronometer mChronometer; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.chronometer); 

     Button button; 

     mChronometer = (Chronometer) findViewById(R.id.chronometer); 

     // Watch for button clicks. 
     button = (Button) findViewById(R.id.start); 
     button.setOnClickListener(mStartListener); 

     button = (Button) findViewById(R.id.stop); 
     button.setOnClickListener(mStopListener); 

     button = (Button) findViewById(R.id.reset); 
     button.setOnClickListener(mResetListener); 

     button = (Button) findViewById(R.id.set_format); 
     button.setOnClickListener(mSetFormatListener); 

     button = (Button) findViewById(R.id.clear_format); 
     button.setOnClickListener(mClearFormatListener); 
    } 

    View.OnClickListener mStartListener = new OnClickListener() { 
     public void onClick(View v) { 
      mChronometer.start(); 
     } 
    }; 

    View.OnClickListener mStopListener = new OnClickListener() { 
     public void onClick(View v) { 
      mChronometer.stop(); 
     } 
    }; 

    View.OnClickListener mResetListener = new OnClickListener() { 
     public void onClick(View v) { 
      mChronometer.setBase(SystemClock.elapsedRealtime()); 
     } 
    }; 

    View.OnClickListener mSetFormatListener = new OnClickListener() { 
     public void onClick(View v) { 
      mChronometer.setFormat("Formatted time (%s)"); 
     } 
    }; 

    View.OnClickListener mClearFormatListener = new OnClickListener() { 
     public void onClick(View v) { 
      mChronometer.setFormat(null); 
     } 
    }; 
} 

R.layout.chronometer:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip" 
    android:gravity="center_horizontal" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <Chronometer android:id="@+id/chronometer" 
     android:format="@string/chronometer_initial_format" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_weight="0" 
     android:paddingBottom="30dip" 
     android:paddingTop="30dip" 
     /> 

    <Button android:id="@+id/start" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@string/chronometer_start"> 
     <requestFocus /> 
    </Button> 

    <Button android:id="@+id/stop" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@string/chronometer_stop"> 
    </Button> 

    <Button android:id="@+id/reset" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@string/chronometer_reset"> 
    </Button> 

    <Button android:id="@+id/set_format" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@string/chronometer_set_format"> 
    </Button> 

    <Button android:id="@+id/clear_format" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="@string/chronometer_clear_format"> 
    </Button> 

</LinearLayout> 

Fügen Sie diese

<string name="chronometer_start">Start</string> 
<string name="chronometer_stop">Stop</string> 
<string name="chronometer_reset">Reset</string> 
<string name="chronometer_set_format">Set format string</string> 
<string name="chronometer_clear_format">Clear format string</string> 
<string name="chronometer_initial_format">Initial format: <xliff:g id="initial-format">%s</xliff:g></string> 
+1

wäre es nicht schöner, wenn Sie auch eine UI Screenshot :) –

+0

die Zeichenfolge chronometer_initial_format fehlt, können Sie es bitte in der gleichen Antwort hinzufügen, so dass wir vermeiden, zu Google gehen, um die Formate zu sehen? –

2

Sie einen Chronometer verwenden, um strings.xml sollte.

Chronometer mChronometer; 
mChronometer = (Chronometer) findViewById(R.id.chronometer1); 
long timeWhenStopped = 0; 

, wenn wir die Chronometer

timeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime(); mChronometer.stop(); 

die Stoppuhr zu stoppen, bevor es

mChronometer.setBase(SystemClock.elapsedRealtime() + timeWhenStopped); mChronometer.start(); 

Zurücksetzen des Chronometer

mChronometer.setBase(SystemClock.elapsedRealtime()); timeWhenStopped = 0;