自定義Chronometer解決app切到后臺(tái)Chronometer時(shí)間停止的bug

問題
當(dāng)APP切到后臺(tái)時(shí)候绩聘,再切回來時(shí)候分飞,發(fā)現(xiàn)時(shí)間還是切出去時(shí)候的時(shí)間喇潘,這是為什么呢渴析?
原來:
當(dāng)APP進(jìn)入后臺(tái)時(shí),會(huì)調(diào)用onWindowVisibilityChanged()方法位隶,Chronometer回調(diào)的onChronometer方法是通過dispatchChronometerTick()方法進(jìn)行回調(diào)的拷窜,但是在updateRunning()方法中有一個(gè)running變量,這個(gè)變量進(jìn)行了一個(gè)是否在顯示在前臺(tái)判斷涧黄,所以在后臺(tái)時(shí)并不會(huì)調(diào)用dispatchChronometerTick()方法

image.png

解決方法自定義Chronometer

package com.cias.vas.lib.widget.tv;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

import org.jetbrains.annotations.NotNull;

import java.util.Formatter;
import java.util.IllegalFormatException;
import java.util.Locale;

/**
 * @Description:
 * @Author: zhoudequn
 * @CreateDate: 2022/5/16 15:12
 */
public class MyChronometer extends AppCompatTextView {

    public interface OnChronometerTickListener {
        void onChronometerTick(MyChronometer myChronometer);
    }

    private long mBase;
    private boolean mVisible;
    private boolean mStarted;
    private boolean mRunning;
    private boolean mLogged;
    private String mFormat;
    private Formatter mFormatter;
    private Locale mFormatterLocale;
    private Object[] mFormatterArgs = new Object[1];
    private StringBuilder mFormatBuilder;
    private OnChronometerTickListener mOnChronometerTickListener;
    private StringBuilder mRecycle = new StringBuilder(8);

    private static final int TICK_WHAT = 2;

    public MyChronometer(@NonNull @NotNull Context context) {
        super(context);
    }

    public MyChronometer(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyChronometer(@NonNull @NotNull Context context, @Nullable @org.jetbrains.annotations.Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mBase = SystemClock.elapsedRealtime();
        updateText(mBase);
    }

    public void setBase(long base) {
        mBase = base;
        dispatchChronometerTick();
        updateText(SystemClock.elapsedRealtime());
    }

    public long getBase() {
        return mBase;
    }

    public void setFormat(String format) {
        mFormat = format;
        if (format != null && mFormatBuilder == null) {
            mFormatBuilder = new StringBuilder(format.length() * 2);
        }
    }

    public String getFormat() {
        return mFormat;
    }

    public void setOnChronometerTickListener(OnChronometerTickListener listener) {
        mOnChronometerTickListener = listener;
    }

    public OnChronometerTickListener getOnChronometerTickListener() {
        return mOnChronometerTickListener;
    }

    public void start() {
        mStarted = true;
        updateRunning();
    }

    public void stop() {
        mStarted = false;
        updateRunning();
    }

    public void setStarted(boolean started) {
        mStarted = started;
        updateRunning();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        mVisible = false;
        updateRunning();
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        updateRunning();
    }

    private synchronized void updateText(long now) {
        long seconds = now - mBase;
        seconds /= 1000;
        String text = DateUtils.formatElapsedTime(mRecycle, seconds);
        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;
            try {
                mFormatter.format(mFormat, mFormatterArgs);
                text = mFormatBuilder.toString();
            } catch (IllegalFormatException ex) {
                if (!mLogged) {
                    mLogged = true;
                }
            }
        }
        setText(text);
    }

    private void updateRunning() {
        boolean running = 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;
        }
    }

    private Handler mHandler = new Handler() {
        public void handleMessage(Message m) {
            if (mRunning) {
                updateText(SystemClock.elapsedRealtime());
                dispatchChronometerTick();
                sendMessageDelayed(Message.obtain(this, TICK_WHAT), 1000);
            }
        }
    };

    void dispatchChronometerTick() {
        if (mOnChronometerTickListener != null) {
            mOnChronometerTickListener.onChronometerTick(this);
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);
        event.setClassName(MyChronometer.class.getName());
    }

    @SuppressLint("NewApi")
    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);
        info.setClassName(MyChronometer.class.getName());
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末篮昧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子笋妥,更是在濱河造成了極大的恐慌懊昨,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件春宣,死亡現(xiàn)場(chǎng)離奇詭異酵颁,居然都是意外死亡嫉你,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門躏惋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幽污,“玉大人,你說我怎么就攤上這事簿姨【辔螅” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵扁位,是天一觀的道長(zhǎng)深寥。 經(jīng)常有香客問我,道長(zhǎng)贤牛,這世上最難降的妖魔是什么惋鹅? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮殉簸,結(jié)果婚禮上闰集,老公的妹妹穿的比我還像新娘。我一直安慰自己般卑,他們只是感情好武鲁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蝠检,像睡著了一般沐鼠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叹谁,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天饲梭,我揣著相機(jī)與錄音,去河邊找鬼焰檩。 笑死憔涉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的析苫。 我是一名探鬼主播兜叨,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼衩侥!你這毒婦竟也來了国旷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤茫死,失蹤者是張志新(化名)和其女友劉穎跪但,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體璧榄,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡特漩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年吧雹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骨杂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涂身。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖搓蚪,靈堂內(nèi)的尸體忽然破棺而出蛤售,到底是詐尸還是另有隱情,我是刑警寧澤妒潭,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布悴能,位于F島的核電站,受9級(jí)特大地震影響雳灾,放射性物質(zhì)發(fā)生泄漏漠酿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一谎亩、第九天 我趴在偏房一處隱蔽的房頂上張望炒嘲。 院中可真熱鬧,春花似錦匈庭、人聲如沸夫凸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽夭拌。三九已至,卻和暖如春衷咽,著一層夾襖步出監(jiān)牢的瞬間鸽扁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工镶骗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留献烦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓卖词,卻偏偏與公主長(zhǎng)得像巩那,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子此蜈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容