首页 > 解决方案 > 如何从 Android 的 Firebase 数据库制作倒数计时器

问题描述

我想从 firebase 数据库中制作倒数计时器。计数器应平等地同步给所有用户,用户不应控制或操纵计时器。

我尝试使用开始时间作为网络提供的日期和最终完成时间,以便在 firebase 数据库中设置。倒数计时器应该计算两个时间的差异。

这是我的代码。

显现

<uses-permission android:name="android.permission.WRITE_SETTINGS"
        tools:ignore="ProtectedPermissions" />

主计数器片段

private CountDownTimer mCountDownTimer;
private TextView mTextViewCountDown;
private String dateEnd="";
private long mTimeLeftInMillis;
    
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    dashboardFragment= inflater.inflate(R.layout.fragment_dashboard, container, false);

    startTimer();

    currentUser= FirebaseAuth.getInstance().getCurrentUser();
    mAuth=FirebaseAuth.getInstance();
    timeRef=FirebaseDatabase.getInstance().getReference();

    InitializeFields();
    mTimeLeftInMillis=dateFormat();

    return dashboardFragment;
}

private long dateFormat() {

    long diff=0;

    SimpleDateFormat formatter=new SimpleDateFormat("dd.MM.yyyy, HH:mm");
    formatter.setLenient(false);

    long endTime=0;
    Date endDate;

    try {
        endDate=formatter.parse(dateEnd);
        endTime=endDate.getTime();
    }catch ( ParseException e){
        e.printStackTrace();
    }

    long startTime = System.currentTimeMillis();

    diff=endTime-startTime;
    return diff;
}

private void startTimer() {

    mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            mTimeLeftInMillis = millisUntilFinished;
            updateCountDownText();
        }
        @Override
        public void onFinish() {

        }
    }.start();
}

private void updateCountDownText() {

    int days=(int) mTimeLeftInMillis/(24*60*60*1000);
    int hours=(int) mTimeLeftInMillis/(60*60*1000)%24;
    int minutes = (int) mTimeLeftInMillis / (60*1000)%60;
    int seconds = (int) mTimeLeftInMillis / 1000%60;
    String timeLeftFormatted = String. format(Locale. getDefault(), "%02d:%02d:%02d:%02d",days,hours, minutes, seconds);
    mTextViewCountDown. setText(timeLeftFormatted);
}

private void InitializeFields() {

    mTextViewCountDown = dashboardFragment.findViewById(R.id.count_down_timer);
}

@Override
public void onStart() {
    super.onStart();
    final DatabaseReference timeRef=FirebaseDatabase.getInstance().getReference().child("Time").child("endTime");
    String timeSettings = android.provider.Settings.System.getString(
        getActivity().getContentResolver(),
        android.provider.Settings.System.AUTO_TIME);
    if (timeSettings.contentEquals("0")) {
        android.provider.Settings.System.putString(
            getActivity().getContentResolver(),
            android.provider.Settings.System.AUTO_TIME, "1");
    }


    timeRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            dateEnd=(String) snapshot.getValue();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
    updateCountDownText();
    startTimer();
}

计数器得到差异但不计数。每次我重新启动应用程序时,它都会获得新的刷新时间,唯一的问题是不算数。

我不知道如何解决它。请任何人。

标签: androidfirebasefirebase-realtime-databasecountdowntimer

解决方案


在我看来,有几个问题。

startTimer()inonCreateView()是无用的,因为没有变量被初始化。

InitializeFields()也无用,因为在操作下方检索图形组件是一种常见做法inflate,您不需要相同创建视图的实例。

In 不知道timeRefin 指的是什么,onCreateView()因为它没有被使用,并且您在方法中有另一个同名的变量onStart()

updateCountDownText()修改了一个图形组件。所以,它必须在 UI Thread 上调用。

然后,在 中onStart(),您在检索dateEnd变量之前启动计时器,因为侦听器模式是异步的。

这是我所说的一些修复

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_dashboard, container, false);
    mTextViewCountDown = dashboardFragment.findViewById(R.id.count_down_timer);

    currentUser = FirebaseAuth.getInstance().getCurrentUser();
    mAuth = FirebaseAuth.getInstance();
    timeRef = FirebaseDatabase.getInstance().getReference();

    mTimeLeftInMillis = dateFormat();

    return v;
}

private long dateFormat() {

    long diff = 0;

    SimpleDateFormat formatter = new SimpleDateFormat("dd.MM.yyyy, HH:mm");
    formatter.setLenient(false);

    long endTime = 0;
    Date endDate;

    try {
        endDate = formatter.parse(dateEnd);
        endTime = endDate.getTime();
    } catch (ParseException e) {
        e.printStackTrace();
    }

    long startTime = System.currentTimeMillis();

    diff = endTime - startTime;
    return diff;
}


private void startTimer() {

    mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 1000) {
        @Override
        public void onTick(long millisUntilFinished) {
            mTimeLeftInMillis = millisUntilFinished;
            updateCountDownText();
        }

        @Override
        public void onFinish() {

        }
    }.start();
}

private void updateCountDownText() {

    getActivity().runOnUiThread(() -> {
        int days = (int) mTimeLeftInMillis / (24 * 60 * 60 * 1000);
        int hours = (int) mTimeLeftInMillis / (60 * 60 * 1000) % 24;
        int minutes = (int) mTimeLeftInMillis / (60 * 1000) % 60;
        int seconds = (int) mTimeLeftInMillis / 1000 % 60;
        String timeLeftFormatted = String.format(Locale.getDefault(), "%02d:%02d:%02d:%02d", days, hours, minutes, seconds);
        mTextViewCountDown.setText(timeLeftFormatted);
    });
}

@Override
public void onStart() {
    super.onStart();
    final DatabaseReference timeRef = FirebaseDatabase.getInstance().getReference().child("Time").child("endTime");
    String timeSettings = android.provider.Settings.System.getString(
            getActivity().getContentResolver(),
            android.provider.Settings.System.AUTO_TIME);
    if (timeSettings.contentEquals("0")) {
        android.provider.Settings.System.putString(
                getActivity().getContentResolver(),
                android.provider.Settings.System.AUTO_TIME, "1");
    }

    timeRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            dateEnd = (String) snapshot.getValue();
            updateCountDownText();
            startTimer();
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }
    });
}

推荐阅读