Red de conocimiento informático - Computadora portátil - ¿Cómo se puede pausar el cronómetro periódicamente en segundo plano en la programación de Android?

¿Cómo se puede pausar el cronómetro periódicamente en segundo plano en la programación de Android?

Eché un vistazo al código fuente de la clase Chronometer. Internamente, utiliza un controlador para enviarse un mensaje a sí mismo con un retraso de un segundo y luego modifica la hora. Al presionar el botón Inicio se activará el método onWindowVisibilityChanged() de Chronometer

Los métodos principales son los siguientes:

public?void?start()?{

mStarted?=?true;

updateRunning();

}

El método anterior consiste en iniciar el temporizador, establecer la variable mStarted en verdadero y ejecutar El método updateRunning once (), updateRunning() se analizará a continuación

public?void?stop()?{

mStarted?=?false;

updateRunning (

}

El método stop() es detener el tiempo, establecer la variable mStarted en falso y ejecutar el método updateRunning() una vez. p>protegido?void? onWindowVisibilityChanged(int?visibilidad)?{

super.onWindowVisibilityChanged(visibilidad);

mVisible?=?visibilidad?==?VISIBLE;

updateRunning() ;

}

El método onWindowVisibilityChanged anterior es un método en View. Este método se activará siempre que cambie el estado visible de View. que presionar el botón Inicio no se detiene, porque el código en este método en realidad se debe a que después de presionar el botón Inicio para activar este método, ya no se volverá a llamar al método de devolución de llamada del oyente que configuró. Después de presionar el botón Inicio, la Vista se vuelve invisible y la variable mVisible se vuelve falsa

private?void?updateRunning()?{

boolean?running?=?mVisible?amp ;amp ;?mIniciado;

if?(¿en ejecución?!=?mEn ejecución)?{

if?(en ejecución)?{

updateText(SystemClock. elapsedRealtime( ));

dispatchChronometerTick();

mHandler.sendMessageDelayed(Message.obtain(mHandler,?TICK_WHAT),?1000);

}? {

mHandler.removeMessages(TICK_WHAT);

}

mRunning?=?running;

}

}

El método updateRunning()? anterior utiliza principalmente dos variables booleanas, mVisible y mStarted, para controlar si se envían mensajes al controlador.

¿privado?Handler?mHandler?=?new?Handler()?{

público?void?handleMessage(Message?m)?{

si?(mRunning)?{

updateText(SystemClock.elapsedRealtime());

dispatchChronometerTick();

sendMessageDelayed(Message.obtain(this,?TICK_WHAT),?1000);

p>

}

}

};

Este controlador ejecuta principalmente el método despachoChronometerTick() y luego envía un mensaje retrasado. a sí mismo

void?dispatchChronometerTick()?{

if?(mOnChronometerTickListener?!=?null)?{

mOnChronometerTickListener.onChronometerTick(this);

}

}

¿El método despachoChronometerTick()? Es para volver a llamar el método onChronometerTick del oyente que configuró

Según Según el análisis anterior, después de presionar el botón Inicio, Chronometer no volverá a llamar a su método de escucha. Esto está controlado por el método onWindowVisibilityChanged() de Chronometer, por lo que su problema no es fácil de resolver. !

La solución que se me ocurre es tomar el código de Chronometer, escribir una clase yo mismo, pegar el código en Chronometer y luego modificar su método onWindowVisibilityChanged(), y luego puedes usar el tuyo propio. apagado. Lo probé y lo implementé

Finalmente, adjunto mi propio código de clase MyChronometer, puedes copiarlo. .

Utilice este control directamente en el archivo de diseño

package?com.lily.demo_listview;

/* *?Copyright?(C)?2008?The?Android?Open?Source? Proyecto * *?Licencia?bajo?la?Licencia?Apache?,?Versión?2.0?(la?Licencia?*?Puede?obtener?una?copia?de?la?Licencia?en * *?.android.internal.R.styleable.Chronometer,?defStyle,?0);

//setFormat(a.getString(com.android.internal.R.styleable.Chronometer_format));

//a.recycle();

init();

p>

}

privado?void?init ()?{

mBase?=?SystemClock.elapsedRealtime();

updateText(mBase) ;

}

/* *

?*?Establece?el?tiempo?que?el?temporizador?de?cuenta?adelante?está?en?referencia.

?*

?*?@param?base?Utilizar?{@link?SystemClock#elapsedRealtime}?time?base.

?*/

public?void?setBase(long ?base)?{

mBase?=?base;

despachoChronometerTick();

Log.d("MiCronómetro",?"dispatchChronometerTick?333" );

updateText(SystemClock.elapsedRealtime());

}

/**

?*?Volver?el? base?time?as?set?through?{@link?#setBase}.

?*/

public?long?getBase()?{

return?mBase;

}

/**

?* ?Establece?la?cadena?de?formato?utilizada?para?la?visualización.?El? ¿El cronómetro?mostrará

?*?esta?cadena,?con?los?primeros?s"?reemplazados? por?el?valor?actual?del?cronómetro?en

?*?"MM:SS"?o?"H:MM:SS"?formulario.

?*

?*?Si?la?cadena?de?formato?

es?nulo,?o?si?nunca?llama?setFormat(),?el

?*?Cronómetro?simplemente?mostrará?el?valor?del?temporizador?en?"MM: SS"?o?"H:MM:SS"

?*?formulario.

?*

?*?@param?formato?el? format?string.

?*/

public?void?setFormat(String?format)?{

mFormat?=?format;

if?(format?=?null?&?mFormatBuilder?==?null)?{

mFormatBuilder?=?new?StringBuilder(format.length()?*? 2);

}

}

/**

?*?Devuelve?la?cadena?de?formato?actual?como ?establecida? a través de?{@link?#setFormat}.

?*/

public?String?getFormat()?{

return?mFormat; >

}

/**

?*?Configura?el?oyente?para?ser?llamado?cuando?cambia?el?cronómetro.

?*?

?*?@param?listener?The?listener.

?*/

public?void?setOnChronometerTickListener( OnChronometerTickListener?listener )?{

mOnChronometerTickListener?=?listener;

}

/**

?*?@return? ?(¿puede?ser?nulo)?eso?es?escuchar?el?cambio?de?cronómetro

?*?eventos.

?*/

público ?OnChronometerTickListener?getOnChronometerTickListener()?{

return?mOnChronometerTickListener;

}

/**

?*? ?arriba.?Esto?no?afecta?la?base?como?configurada?desde?{@link?#setBase},?sólo

?*?la?visualización?de?vista.

?*?

?*?El cronómetro?funciona?programando?mensajes?regularmente?al?manipulador,?incluso?cuando?

?*?Widget?no?visible?

e.?Para?asegurarse?de?que?no?ocurrieran?fugas?de?recursos,?el?usuario?debería?

?*?asegurarse?de?que?cada?llamada?start()? ¿tiene?una?llamada?reciproca?a?{@link?#stop}.?

?*/

public?void?start()?{

mStarted?=?true;

updateRunning();

}

/**

?*?Stop?counting ?arriba.?Esto?no?afecta?la?base?como?configurada?desde?{@link?#setBase},?sólo

?*?la?visualización?de?vista.

?*?

?*?Esto?detiene?los?mensajes?al?controlador,?liberando?efectivamente?recursos?que?

? *?ser?sostenido?mientras?el?cronómetro?está?en?funcionamiento,?vía?{@link?#start}.?

?*/

pública?void?parada ()?{

mIniciado?=?false;

updateRunning();

}

/**

?*?¿Lo mismo?que?llamar?{@link?#start}?o?{@link?#stop}.

?*?@hide?pending?API?council ?aprobación

?*/

pública?void?setStarted(boolean?started)?{

mStarted?=?started;

updateRunning();

}

@Override

protected?void?onDetachedFromWindow()?{

super.onDetachedFromWindow() ;

mVisible?=?false;

updateRunning();

Log.d("MyChronmeter",?"onDetachedFromWindow()" mVisible);

}

@Override

protected?void?onWindowVisibilityChanged(int?visibility)?{

super.onWindowVisibilityChanged(visibilidad);

updateRunning();

}

¿privado?sincronizado?void?updateText(long?now)?{

¿long?segundos? =?ahora?-?mBase;

segundos?/=?

1000;

String?text?=?DateUtils.formatElapsedTime(mRecycle,?segundos);

if?(mFormat?!=?null)?{

Locale?loc?=?Locale.getDefault();

if?(mFormatter?==?null?||?!loc.equals(mFormatterLocale))?{

mFormatterLocale?=?loc;

mFormatter?=?new?Formatter(mFormatBuilder,?loc);

}

mFormatBuilder.setLength(0);

mFormatterArgs[0]?=?text;

¿intentar?{

mFormatter.format(mFormat,?mFormatterArgs);

texto ?=?mFormatBuilder.toString();

}?catch?(IllegalFormatException?ex)?{

if?(!mLogged)?{

Registrar .w(TAG,?"Illegal?format?string:?"? ?mFormat);

mLogged?=?true;

}

}

}

setText(texto);

}

privado?void?updateRunning()?{

boolean?running?=?mStarted;

if?(running?!=?mRunning)?{

if?(running)?{

updateText( SystemClock.elapsedRealtime());

despachoChronometerTick();

Log.d("MyChronometer",?"dispatchChronometerTick?222");

mHandler. sendMessageDelayed(Message.obtain(mHandler,?TICK_WHAT),?1000);

}?else?{

mHandler.removeMessages(TICK_WHAT);

}

mRunning?=?running;

}

}

privado?Handler?mHandler?=?new?Handler()? {

public?void?handleMessage(Message?m)?{

if?(mRunning)?{

updateText(SystemClock.elapsedRealtime());

despachoChronometerTick();

Log.d("MyChronometer",? "dispatchChronometerTick?111");

sendMessageDelayed(Message.obtain(this,? TICK_WHAT),?1000);

}

}

};

void?dispatchChronometerTick()?{

if?(mOnChronometerTickListener?=?null)?{

mOnChronometerTickListener.onChronometerTick(this);

//Log.d("MyChronometer",?"Método de devolución de llamada " );

}

}

@SuppressLint("NewApi")?@Override

public?void?onInitializeAccessibilityEvent(AccessibilityEvent ? evento)?{

super.onInitializeAccessibilityEvent(evento);

evento.setClassName(MyChronometer.class.getName());

}

@SuppressLint("NewApi")?@Override

public?void?onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo?info)?{

super.onInitializeAccessibilityNodeInfo(info);

info.setClassName(MyChronometer.class.getName());

}

}