Xamarin.Android中用户登录时在TextView显示计时器的实现方法
Got it, let's tackle this timer display for your logged-in users in Xamarin.Android. Based on the code you shared, here's a step-by-step implementation that fits with your existing setup:
实现登录后计时器显示的方案
1. 完善ViewModel层(DashboardViewModel)
Since you're using a ViewModel pattern (from your LoginViewModel code), we'll add timer logic to your Dashboard page's ViewModel. This keeps the UI and business logic separated, and ensures clean lifecycle management.
using System; using System.Timers; using System.ComponentModel; public class DashboardViewModel : INotifyPropertyChanged { private Timer _updateTimer; private TimeSpan _totalWorkTime; private DateTime _loginTimestamp; // 绑定到TextView的显示文本 public string WorkTimerText { get => $"Dzisiaj pracujesz już:\n{_totalWorkTime:hh\\:mm\\:ss}"; set => OnPropertyChanged(nameof(WorkTimerText)); } public DashboardViewModel() { // 获取登录时记录的时间(从你的_appVariables全局变量中) _loginTimestamp = _appVariables.logDate; StartTimer(); } private void StartTimer() { // 每秒更新一次计时器 _updateTimer = new Timer(1000); _updateTimer.Elapsed += OnTimerTick; // 先计算初始时长,避免延迟显示 UpdateWorkDuration(); _updateTimer.Start(); } private void OnTimerTick(object sender, ElapsedEventArgs e) { UpdateWorkDuration(); // 必须在主线程更新UI,避免跨线程异常 Android.App.Application.SynchronizationContext.Post(_ => { OnPropertyChanged(nameof(WorkTimerText)); }, null); } private void UpdateWorkDuration() { _totalWorkTime = DateTime.Now - _loginTimestamp; } // 清理计时器,防止内存泄漏 public void DisposeTimer() { _updateTimer?.Stop(); _updateTimer?.Dispose(); } // INotifyPropertyChanged实现,用于通知UI更新 public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 绑定View层(DashboardActivity)
Next, connect the ViewModel to your Dashboard Activity and handle the UI binding, plus lifecycle events to clean up the timer:
using Android.App; using Android.OS; using Android.Widget; [Activity(Label = "Dashboard")] public class DashboardActivity : Activity { private DashboardViewModel _viewModel; private TextView _timeTextView; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.Dashboard); // 替换成你的Dashboard布局文件名 // 找到布局中的TextView _timeTextView = FindViewById<TextView>(Resource.Id.timeTextView); // 初始化ViewModel _viewModel = new DashboardViewModel(); // 绑定属性变化事件 _viewModel.PropertyChanged += ViewModel_PropertyChanged; // 设置初始文本 _timeTextView.Text = _viewModel.WorkTimerText; } private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(_viewModel.WorkTimerText)) { _timeTextView.Text = _viewModel.WorkTimerText; } } // 页面销毁时清理计时器和事件绑定 protected override void OnDestroy() { base.OnDestroy(); _viewModel.DisposeTimer(); _viewModel.PropertyChanged -= ViewModel_PropertyChanged; } // 可选:页面暂停时停止计时器,恢复时重启 protected override void OnPause() { base.OnPause(); _viewModel.DisposeTimer(); } protected override void OnResume() { base.OnResume(); _viewModel.StartTimer(); } }
3. 关键注意事项
- 线程安全:Timer的
Elapsed事件运行在后台线程,所以必须用SynchronizationContext.Post(或RunOnUiThread)切换到主线程更新UI,否则会抛出跨线程异常。 - 内存泄漏防护:Always stop and dispose the timer, plus unbind the
PropertyChangedevent when the activity is destroyed—this prevents memory leaks from lingering timer references. - 时间格式化:The
hh\\:mm\\:ssformat displays hours, minutes, and seconds. If you need to include days, use%d\\:hh\\:mm\\:ssinstead. - 全局变量验证:Ensure
_appVariables.logDateis correctly set to the user's login time in your LoginViewModel (your existing code already does this, double-check it's not null/empty).
内容的提问来源于stack exchange,提问作者felekmenelek
相关产品推荐
相关产品推荐

