Android编程中chronometer在后台怎么才能定时暂停
我看了下Chronometer这个类的源码,他内部就是用一个handler延迟一秒给自己发送一次消息,然后修改时间。按Home键,会触发Chronometer的onWindowVisibilityChanged()方法
主要方法有下面几个方法:
publicvoidstart(){
mStarted=true;
updateRunning();
}
上面方法是启动计时器,将mStarted变量设置为true,并执行一次updateRunning()方法,updateRunning()会在下面讲到
publicvoidstop(){
mStarted=false;
updateRunning();
}
stop()方法是停止计时,将mStarted变量设置为false,并执行一次updateRunning()方法
protectedvoidonWindowVisibilityChanged(intvisibility){
super.onWindowVisibilityChanged(visibility);
mVisible=visibility==VISIBLE;
updateRunning();
}
上面的onWindowVisibilityChanged方法,是View里面的方法,只要View的可见状态发生改变了都会触发这个方法,很显然你说按Home键时间没停止,就是因为这个方法里面的代码,实际上是因为按Home键触发这个方法以后,就不再回调你设置的监听器的回调方法。按Home键后,View变为不可见状态,变量mVisible变成了false
privatevoidupdateRunning(){
booleanrunning=mVisible&&mStarted;
if(running!=mRunning){
if(running){
updateText(SystemClock.elapsedRealtime());
dispatchChronometerTick();
mHandler.sendMessageDelayed(Message.obtain(mHandler,TICK_WHAT),1000);
}else{
mHandler.removeMessages(TICK_WHAT);
}
mRunning=running;
}
}
上面的updateRunning()方法主要是工具mVisible和mStarted这2个boolean变量来控制是否向handler发送消息。
privateHandlermHandler=newHandler(){
publicvoidhandleMessage(Messagem){
if(mRunning){
updateText(SystemClock.elapsedRealtime());
dispatchChronometerTick();
sendMessageDelayed(Message.obtain(this,TICK_WHAT),1000);
}
}
};
这个Handler主要是执行dispatchChronometerTick()方法再向它自己发送一条延时消息
voiddispatchChronometerTick(){
if(mOnChronometerTickListener!=null){
mOnChronometerTickListener.onChronometerTick(this);
}
}
dispatchChronometerTick()方法就是回调你设置的监听器的onChronometerTick方法
根据以上分析,按Home键之后,Chronometer就不会回调你的监听器方法,这个是受Chronometer的onWindowVisibilityChanged()方法控制的,所以你的问题不好解决!!
我能想到的解决方式就是把Chronometer的代码拿过来,自己写一个类,粘贴上Chronometer里面的代码,然后再修改它的onWindowVisibilityChanged()方法,然后就可以用自己的这个计时器了。我测试过了,实现了
最后附上我自己的MyChronometer类代码,你可以复制一下。。在布局文件里直接用这个控件
packagecom.lily.demo_listview;
/*
*Copyright(C)2008TheAndroidOpenSourceProject
*
*LicensedundertheApacheLicense,Version2.0(the"License");
*youmaynotusethisfileexceptincompliancewiththeLicense.
*YoumayobtainacopyoftheLicenseat
*
*
*
*Unlessrequiredbyapplicablelaworagreedtoinwriting,software
*distributedundertheLicenseisdistributedonan"ASIS"BASIS,
*WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
*SeetheLicenseforthespecificlanguagegoverningpermissionsand
*limitationsundertheLicense.
*/
importjava.util.Formatter;
importjava.util.IllegalFormatException;
importjava.util.Locale;
importandroid.annotation.SuppressLint;
importandroid.content.Context;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.os.SystemClock;
importandroid.text.format.DateUtils;
importandroid.util.AttributeSet;
importandroid.util.Log;
importandroid.view.accessibility.AccessibilityEvent;
importandroid.view.accessibility.AccessibilityNodeInfo;
importandroid.widget.RemoteViews.RemoteView;
importandroid.widget.TextView;
/**
*Classthatimplementsasimpletimer.
*<p>
*Youcangiveitastarttimeinthe{@linkSystemClock#elapsedRealtime}timebase,
*anditcountsupfromthat,orifyoudon'tgiveitabasetime,itwillusethe
*timeatwhichyoucall{@link#start}.Bydefaultitwilldisplaythecurrent
*timervalueintheform"MM:SS"or"H:MM:SS",oryoucanuse{@link#setFormat}
*toformatthetimervalueintoanarbitrarystring.
*
*@attrrefandroid.R.styleable#Chronometer_format
*/
@RemoteView
publicclassMyChronometerextendsTextView{
privatestaticfinalStringTAG="Chronometer";
/**
*Acallbackthatnotifieswhenthechronometerhasincrementedonitsown.
*/
publicinterfaceOnChronometerTickListener{
/**
*Notificationthatthechronometerhaschanged.
*/
voidonChronometerTick(MyChronometerchronometer);
}
privatelongmBase;
privatebooleanmVisible;
privatebooleanmStarted;
privatebooleanmRunning;
privatebooleanmLogged;
privateStringmFormat;
privateFormattermFormatter;
privateLocalemFormatterLocale;
privateObject[]mFormatterArgs=newObject[1];
privateStringBuildermFormatBuilder;
privateOnChronometerTickListenermOnChronometerTickListener;
privateStringBuildermRecycle=newStringBuilder(8);
privatestaticfinalintTICK_WHAT=2;
/**
*InitializethisChronometerobject.
*Setsthebasetothecurrenttime.
*/
publicMyChronometer(Contextcontext){
this(context,null,0);
}
/**
*Initializewithstandardviewlayoutinformation.
*Setsthebasetothecurrenttime.
*/
publicMyChronometer(Contextcontext,AttributeSetattrs){
this(context,attrs,0);
}
/**
*Initializewithstandardviewlayoutinformationandstyle.
*Setsthebasetothecurrenttime.
*/
publicMyChronometer(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
//TypedArraya=context.obtainStyledAttributes(
//attrs,
//com.android.internal.R.styleable.Chronometer,defStyle,0);
//setFormat(a.getString(com.android.internal.R.styleable.Chronometer_format));
//a.recycle();
init();
}
privatevoidinit(){
mBase=SystemClock.elapsedRealtime();
updateText(mBase);
}
/**
*Setthetimethatthecount-uptimerisinreferenceto.
*
*@parambaseUsethe{@linkSystemClock#elapsedRealtime}timebase.
*/
publicvoidsetBase(longbase){
mBase=base;
dispatchChronometerTick();
Log.d("MyChronometer","dispatchChronometerTick333");
updateText(SystemClock.elapsedRealtime());
}
/**
*Returnthebasetimeassetthrough{@link#setBase}.
*/
publiclonggetBase(){
returnmBase;
}
/**
*Setstheformatstringusedfordisplay.TheChronometerwilldisplay
*thisstring,withthefirst"%s"replacedbythecurrenttimervaluein
*"MM:SS"or"H:MM:SS"form.
*
*Iftheformatstringisnull,orifyounevercallsetFormat(),the
*Chronometerwillsimplydisplaythetimervaluein"MM:SS"or"H:MM:SS"
*form.
*
*@paramformattheformatstring.
*/
publicvoidsetFormat(Stringformat){
mFormat=format;
if(format!=null&&mFormatBuilder==null){
mFormatBuilder=newStringBuilder(format.length()*2);
}
}
/**
*Returnsthecurrentformatstringassetthrough{@link#setFormat}.
*/
publicStringgetFormat(){
returnmFormat;
}
/**
*Setsthelistenertobecalledwhenthechronometerchanges.
*
*@paramlistenerThelistener.
*/
publicvoidsetOnChronometerTickListener(OnChronometerTickListenerlistener){
mOnChronometerTickListener=listener;
}
/**
*@returnThelistener(maybenull)thatislisteningforchronometerchange
*events.
*/
publicOnChronometerTickListenergetOnChronometerTickListener(){
returnmOnChronometerTickListener;
}
/**
*Startcountingup.Thisdoesnotaffectthebaseassetfrom{@link#setBase},just
*theviewdisplay.
*
*Chronometerworksbyregularlyschedulingmessagestothehandler,evenwhenthe
*Widgetisnotvisible.Tomakesureresourceleaksdonotoccur,theusershould
*makesurethateachstart()callhasareciprocalcallto{@link#stop}.
*/
publicvoidstart(){
mStarted=true;
updateRunning();
}
/**
*Stopcountingup.Thisdoesnotaffectthebaseassetfrom{@link#setBase},just
*theviewdisplay.
*
*Thisstopsthemessagestothehandler,effectivelyreleasingresourcesthatwould
*beheldasthechronometerisrunning,via{@link#start}.
*/
publicvoidstop(){
mStarted=false;
updateRunning();
}
/**
*Thesameascalling{@link#start}or{@link#stop}.
*@hidependingAPIcouncilapproval
*/
publicvoidsetStarted(booleanstarted){
mStarted=started;
updateRunning();
}
@Override
protectedvoidonDetachedFromWindow(){
super.onDetachedFromWindow();
mVisible=false;
updateRunning();
Log.d("MyChronmeter","onDetachedFromWindow()"+mVisible);
}
@Override
protectedvoidonWindowVisibilityChanged(intvisibility){
super.onWindowVisibilityChanged(visibility);
updateRunning();
}
privatesynchronizedvoidupdateText(longnow){
longseconds=now-mBase;
seconds/=1000;
Stringtext=DateUtils.formatElapsedTime(mRecycle,seconds);
if(mFormat!=null){
Localeloc=Locale.getDefault();
if(mFormatter==null||!loc.equals(mFormatterLocale)){
mFormatterLocale=loc;
mFormatter=newFormatter(mFormatBuilder,loc);
}
mFormatBuilder.setLength(0);
mFormatterArgs[0]=text;
try{
mFormatter.format(mFormat,mFormatterArgs);
text=mFormatBuilder.toString();
}catch(IllegalFormatExceptionex){
if(!mLogged){
Log.w(TAG,"Illegalformatstring:"+mFormat);
mLogged=true;
}
}
}
setText(text);
}
privatevoidupdateRunning(){
booleanrunning=mStarted;
if(running!=mRunning){
if(running){
updateText(SystemClock.elapsedRealtime());
dispatchChronometerTick();
Log.d("MyChronometer","dispatchChronometerTick222");
mHandler.sendMessageDelayed(Message.obtain(mHandler,TICK_WHAT),1000);
}else{
mHandler.removeMessages(TICK_WHAT);
}
mRunning=running;
}
}
privateHandlermHandler=newHandler(){
publicvoidhandleMessage(Messagem){
if(mRunning){
updateText(SystemClock.elapsedRealtime());
dispatchChronometerTick();
Log.d("MyChronometer","dispatchChronometerTick111");
sendMessageDelayed(Message.obtain(this,TICK_WHAT),1000);
}
}
};
voiddispatchChronometerTick(){
if(mOnChronometerTickListener!=null){
mOnChronometerTickListener.onChronometerTick(this);
//Log.d("MyChronometer","回调方法");
}
}
@SuppressLint("NewApi")@Override
publicvoidonInitializeAccessibilityEvent(AccessibilityEventevent){
super.onInitializeAccessibilityEvent(event);
event.setClassName(MyChronometer.class.getName());
}
@SuppressLint("NewApi")@Override
publicvoidonInitializeAccessibilityNodeInfo(AccessibilityNodeInfoinfo){
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(MyChronometer.class.getName());
}
}
1G可移动硬盘原来的fat32格式变成了raw,无法格式化
1、使用EasyRecovery Pro 6.06,选择数据恢复---》Advanced Recovery(选用高级选项自定义数据恢复功能);
2、选择已变为RAW格式的盘符,点击下角的高级选项;
3、在文件系统扫描中,文件系统选“NTFS",点高级扫描,选择右下角的“高级选项”,把簇大小和数据起始位置都设为0;
4、点击分区设置,使用MFT方式(这点一定不能错);然后确定;
5、点击下一步,开始扫描文件系统,然后就是等~~~~~~~~~~~~~~~,要的时间比较长,要耐心。完成后就会发现找到了一个NTFS的盘符,再点击找到的盘符,开始扫描;
6、扫描完成后你就会发现所有的文件都已找到,然后点击恢复,选择一个可用的盘来存你恢复的文件就行;
7、最后格式化出问题的盘~~~把恢复的文件拷回去~~~~~~OK一切都完好如初。