2012-09-14 30 views
5

bài đăng thất vọng ....android CountDownTimer - last onTick không được gọi - giải pháp sạch sẽ để sử dụng?

Tôi vừa vấp vào "CountDownTimer - last onTick không được gọi là" nhiều sự cố đã được báo cáo tại đây.

bản demo đơn giản cho thấy vấn đề

package com.example.gosh; 

import android.app.Activity; 
import android.os.Bundle; 
import android.os.CountDownTimer; 
import android.util.Log; 

public class CountDownTimerSucksActivity extends Activity { 

int iDontWantThis = 0; // choose 100 and it works yet ... 

private static final String TAG = "CountDownTimerSucksActivity"; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    new MyCountDownTimer(10000 + iDontWantThis , 1000).start(); 
} 

class MyCountDownTimer extends CountDownTimer { 

    long startSec; 

    public MyCountDownTimer(long millisInFuture, long countDownInterval) { 
     super(millisInFuture, countDownInterval); 
     // TODO Auto-generated constructor stub 
     startSec = System.currentTimeMillis() ; 
    } 

    @Override 
    public void onFinish() { 
     // TODO Auto-generated method stub 
     Log.e(TAG, " onFinish (" + getSeconds() + ")"); 
    } 

    @Override 
    public void onTick(long millisUntilFinished) { 
     // TODO Auto-generated method stub 
     Log.e(TAG, millisUntilFinished + " millisUntilFinished" + " (" + getSeconds() + ")"); 

    } 

    protected long getSeconds() { 
     return (((System.currentTimeMillis() - startSec)/1000) % 60); 

    } 

} 

} 

Các logcat đầu ra từ một thử nghiệm chạy ...

logcat ouput

Như bạn có thể thấy các cuộc gọi cuối cùng onTick đang xảy ra với 1963ms millisUntilFinished, sau đó cuộc gọi tiếp theo là onFinished gần 2 giây sau đó. Chắc chắn là một hành vi lỗi. Tôi đã tìm thấy nhiều bài viết về điều này nhưng chưa có giải pháp sạch. Một trong những tôi bao gồm trong mã nguồn, nếu bạn thiết lập trường iDontWantThis đến 100 nó hoạt động.

Tôi không nhớ cách giải quyết trong các lĩnh vực nhỏ nhưng điều này có vẻ như một chức năng cốt lõi mà tôi không thể hiểu được nó vẫn chưa được khắc phục. Bạn đang làm gì để có một giải pháp sạch cho việc này?

Thanks a lot

martin

UPDATE:

Một sửa đổi rất hữu ích của CountDownTimer bởi Sam mà không surpresses tick trước do chậm trễ ms nội bộ và cũng ngăn ngừa sự tích tụ của sự chậm trễ ms với mỗi đánh dấu theo thời gian có thể được tìm thấy here

Trả lời

8

Hành vi bạn đang gặp phải thực sự được xác định rõ ràng trong CountdownTimer mã; have a look at the source.

Thông báo bên trong của handleMessage(), nếu thời gian còn lại nhỏ hơn khoảng thời gian, nó rõ ràng không gọi onTick() và chỉ bị chậm trễ cho đến khi hoàn thành.

Thông báo, mặc dù, từ nguồn mà CountdownTimer chỉ là một trình bao bọc rất mỏng trên Handler, là thành phần thời gian thực của khung công tác Android. Để giải quyết vấn đề này, bạn có thể dễ dàng tạo bộ đếm thời gian của riêng bạn từ nguồn này (ít hơn 150 dòng) và loại bỏ hạn chế này để nhận được cuộc gọi đánh dấu cuối cùng của bạn.

+0

Cảm ơn rất nhiều, khá mới mẻ đối android và tôi havent đã bước để thực sự nhìn vào mã nguồn của nó trong những trường hợp như thế. Cảm ơn rất nhiều vì đã chỉ cho tôi bước đó. Tôi sẽ thực hiện CountDownTimer của riêng mình như được đề xuất luôn gọi onTick nếu millisUntilFinished> 0 và tôi có thể kiểm tra dễ dàng nếu số milli còn lại cho phép tôi muốn làm gì (thực ra tôi chỉ cần đồng hồ đếm ngược hiển thị 6,5,4,3,2 , 1,0) – dorjeduck

+0

chỉ vì mục đích hoàn thành, xóa bỏ phần còn lại nếu khối lệnh thực hiện lệnh onTick được gọi bất cứ khi nào có millis còn lại ------------------- ---------------------------------------------} else if (millisLeft dorjeduck

2

Tôi nghĩ rằng sự thất vọng đến từ một kỳ vọng không chính xác của những gì một đánh dấu nên được. Như câu trả lời khác được lưu ý, hành vi này là cố ý. Một cách khác có thể xử lý này là chỉ cần chỉ định một khoảng nhỏ hơn. Nếu bạn đang thực hiện một số loại đồng hồ đếm ngược ví dụ, nó sẽ không làm tổn thương để thay đổi khoảng thời gian đến 500. Nếu điều quan trọng là một số công việc chỉ được thực hiện khi giây thay đổi, sau đó bạn có thể làm điều đó quá bằng cách lưu trữ kết quả của getSeconds() và chỉ thực hiện công việc đó khi giá trị đó thay đổi.

Nếu CountdownTimer được thay đổi để luôn đánh dấu lần cuối cùng ngay cả khi thời gian còn lại nhỏ hơn khoảng thời gian, tôi chắc chắn StackOverflow sẽ có một loạt câu hỏi như "tại sao tôi không có đủ thời gian trong dấu cuối cùng CountdownTimer?"

+0

Bạn đúng Tôi chỉ mong đợi hành vi khác nhau đó là nguồn gốc của sự thất vọng. Tôi ngạc nhiên về hành vi dự định nó không được đề cập trong tài liệu API, cụ thể như trong logcat ở trên nó có thể được nhìn thấy đồng hồ đếm ngược nó thực sự là "muộn" với mỗi đánh dấu khi nó cháy 47 ms sau hơn giâyLeft/khoảng thời gian và 47ms đó khiến cho onTick không được gọi như tôi mong đợi. Chỉ cần tưởng tượng trường hợp bạn cung cấp cho 4 giờ như intervall, những người sẽ mong đợi onTick không được gọi là vì 43ms. Nhưng có đó là vấn đề với kỳ vọng;) – dorjeduck

1

Tôi không hiểu tại sao bạn nói rằng đó là hành vi cố ý, API cho biết chính xác:

'Lên lịch đếm ngược cho đến một thời điểm trong tương lai, với các thông báo thường xuyên trên các khoảng thời gian trên đường đi'

.
new CountDownTimer(30000, 1000) { 

    public void onTick(long millisUntilFinished) { 
     mTextField.setText("seconds remaining: " + millisUntilFinished/1000); 
    } 

    public void onFinish() { 
     mTextField.setText("done!"); 
    } 
}.start(); 

nếu bạn thiết lập thời gian để 30 giây, và countDownInterval đến 1000, như API nói thường xuyên, nó nên được bắn chính xác gấp 30 lần. tôi nghĩ rằng nó không phải là một hành vi cố ý nhưng việc thực hiện sai.

Các giải pháp phải là một bằng Sam đây đề xuất:

android CountDownTimer - additional milliseconds delay between ticks

+0

Cảm ơn Juan - giải pháp của Sam đã được đề cập đến trong bản cập nhật của bài đăng. – dorjeduck

Các vấn đề liên quan