Android Chronometer own implementation

2019-05-23 20:51发布

问题:

I've developed an own implementation of a Chronometer. I did the follow:

  1. Create a Service (CronoService), that use a Runnable object that execute the thread. The Runnable will loop each 0.1 secs.

  2. Messenger Object that will receive messages from Ui to Start, Pause or Resume the Chronometer.

  3. Intent that will broadcast the time after each loop of the Runnable object.

The code is:

public class CronoService extends Service {

public static final int PARAR = 0;
public static final int EMPEZAR = 1;
public static final int ESTABLECER_TIEMPO = 2;

private static final String TAG = "BroadcastService";

public static final String BROADCAST_ACTION = "jose.planilla.mostrartiempo";
final Messenger mMessenger = new Messenger(new IncomingHandler());

private final Handler handler = new Handler();
private Intent intent;
private long mDec;
private long mTotalMilis;
private long mLastMilis;
private long mElapsedTime;
private long mCurrentMilis;
private int mSeconds;
private int mMin;

private Runnable sendUpdatesToUI = new Runnable() {
    public void run() {
        mCurrentMilis = System.currentTimeMillis();
        mElapsedTime = mCurrentMilis - mLastMilis;
        mLastMilis = mCurrentMilis;
        mTotalMilis += mElapsedTime;
        DisplayLoggingInfo();
        handler.postDelayed(this, 100); // 0.1 seconds
        Log.d("run()", String.valueOf(mTotalMilis));
    }
};  



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

    intent = new Intent(BROADCAST_ACTION);

}

@Override
public void onStart(Intent intent, int startId){
    mTotalMilis = intent.getLongExtra("milis", 0);
    handler.removeCallbacks(sendUpdatesToUI);
    handler.postDelayed(sendUpdatesToUI, 100); // 0.1 second 
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "onStart()");
    mLastMilis = mElapsedTime = System.currentTimeMillis(); 
    mTotalMilis = intent.getLongExtra("milis", 0);
    handler.removeCallbacks(sendUpdatesToUI);
    DisplayLoggingInfo();
    //handler.postDelayed(sendUpdatesToUI, 100); // 0.1 second 

    return START_NOT_STICKY;
}    

@Override
public IBinder onBind(Intent arg0) {
    return mMessenger.getBinder();
}


private void DisplayLoggingInfo() { 
    String tiempo;

    mDec = mTotalMilis % 1000;
    mDec = mDec / 100;
    mSeconds = (int) (mTotalMilis / 1000);
    mMin = mSeconds / 60;
    mSeconds = mSeconds % 60;
    tiempo = "" + mDec;

    if(mSeconds < 10)
        tiempo = ":0" + mSeconds + "." + tiempo;
    else
        tiempo = ":" + mSeconds + "." + tiempo; 

    if(mMin < 10 )
        tiempo = "0" + mMin + tiempo;
    else
        tiempo = mMin + tiempo;

    intent.putExtra("tiempo", tiempo);
    intent.putExtra("milis", mTotalMilis);
    sendBroadcast(intent);
}

@Override
public void onDestroy() {       
    handler.removeCallbacks(sendUpdatesToUI);
    super.onDestroy();
}

public void pause(){
    handler.removeCallbacks(sendUpdatesToUI);
}

public void resume(){
    handler.postDelayed(sendUpdatesToUI, 100);
}

class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg){ 
        switch(msg.what) {
            case PARAR:
                pause();
                break;
            case EMPEZAR:
                resume();
                break;
            case ESTABLECER_TIEMPO: 
                mTotalMilis = (Long) msg.obj;
                break;
            default:
                super.handleMessage(msg);
        }
    }
}

My problem is that the my Chronometer is a bit slower than a normal one. It loses o bit of time en each seconds. I'm doing something wrong, but I can't find the problem. Thanks a lot.

EDIT Working code updated.

回答1:

There's an easier way that has worked fine for me: playing with Sistem.getCurrentMillis()

Take a look at this: Android: Chronometer with Milliseconds?