2010-06-30 48 views
9

Đây là tình huống của tôi: Tôi đang xây dựng một trò chơi cho android và hoạt động của trò chơi của tôi bao gồm một chế độ xem bề mặt tùy chỉnh có chủ đề cho logic trò chơi và hiển thị. Kiến trúc tương tự như bản trình diễn LunarLander từ trang web của Google."Chủ đề đã bắt đầu" khi tiếp tục hoạt động

Khi hoạt động bắt đầu nó tạo ra surfaceView và gọi phương pháp này:

@Override 
    public void surfaceCreated(SurfaceHolder holder) 
    { 
     renderThread.start(); 
    } 

Khi tôi bấm nút home để thoát khỏi trò chơi, phương pháp onPause() được gọi, trong đó kêu gọi surfaceDestroyed(). Trong surfaceDestroyed Tôi dừng trò chơi Chủ đề bằng cách gọi:

@Override 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     synchronized(holder) 
     { 
      renderThread.stop(); 
     } 
    }  

Ứng dụng này sẽ hoạt động bình thường. Sau đó, khi tôi khởi chạy lại ứng dụng bằng cách nhấn vào biểu tượng, tôi nhận được thông báo "Chủ đề đã bắt đầu" trong nhật ký cùng với cửa sổ bật lên "lực đóng" trên màn hình. Thông báo này xảy ra khi hoạt động đi vào phương thức "surfaceCreated" khi nó gọi start() trên chuỗi render.

Bây giờ tôi đã xem xét nó hàng giờ và không thể hiểu tại sao điều này xảy ra. Tôi tin rằng chủ đề của tôi bị dừng lại khi tôi đóng ứng dụng để tôi không hiểu tại sao nó nói nó đã bắt đầu.

Trả lời

8

Những phương pháp đó không làm những gì bạn nghĩ. Từ số API doc:

Không bao giờ là hợp pháp để bắt đầu một chuỗi nhiều lần.

Và:

public final void stop() - Deprecated. Phương pháp này vốn không an toàn.

Nếu bạn muốn tạm dừng một chuỗi, bạn phải sử dụng Object.wait()Objecft.notifyAll() từ trong chuỗi.

+1

Xin chào, cảm ơn bạn đã trả lời. Tôi đã thay thế stop() bằng một phép nối() trong một vòng lặp while. Tôi tin rằng nó đợi trước khi dừng sợi chỉ. Nhưng tôi vẫn còn có cùng một vấn đề, tôi đang thiếu một cái gì đó? Khi bắt đầu chuỗi. Tôi hiểu rằng thread không thể được bắt đầu nhiều hơn một lần do đó thông báo lỗi. Vì vậy, bạn có nghĩ rằng tôi nhận được lỗi này chỉ vì thread không được dừng lại đúng cách? Cảm ơn – NioX5199

+1

@ NioX5199: không, tham gia() cũng không dừng chuỗi, nó chờ nó tự hoàn thành. Bạn nhận được lỗi vì Chủ đề đã được bắt đầu. Chủ đề * không thể * bị "dừng" và khởi động lại. Như tôi đã viết: để thực hiện tạm dừng luồng cho đến khi điều kiện được đáp ứng, bạn sử dụng Object.wait(). –

+0

Có lẽ anh ta cũng không nên làm theo cách đó. Việc tạo lại luồng có lẽ là một cách tiếp cận tốt hơn. – alexanderblom

0

Một giải pháp xấu, nhưng nó hoạt động ..

public void surfaceCreated(SurfaceHolder holder) { 
     try{ 
     _thread.setRunning(true); 
     _thread.start(); 
     }catch(Exception ex){ 
      _thread = new TutorialThread(getHolder(), this); 
      _thread.start(); 
     } 

    } 

chỉnh được nhiệt liệt hoan nghênh.

+0

Trong khi điều này sẽ làm việc (fsvo), nó thường không phải là một ý tưởng tốt để bắt các vấn đề sẽ-nilly và sau đó để thử và sửa chữa. Thay vào đó, hãy * chủ động * và đưa ra Ngoại lệ trở lại ý nghĩa của chúng. –

5

Theo ý kiến ​​của bạn, bạn không nên đóng gói mã của bạn vào một lớp con của Chủ đề nếu bạn có ý định bắt đầu và dừng Chủ đề thường xuyên (ví dụ làm vì nó làm cho mã ngắn hơn). Sử dụng Runnable để thay thế. Bằng cách đó bạn có thể dừng và loại bỏ Thread cũ khi bạn muốn và tạo một đối tượng Thread mới để thực thi Runnable khi bạn cần khởi động lại nó.

private TutorialRunnable tutorialRunnable; 

... 

// Synchronization and error checking omitted for brevity. 
public void surfaceCreated(SurfaceHolder holder) { 
    thread = new Thread(tutorialRunnable); 
    thread.start(); 
} 

public void surfaceDestroyed(SurfaceHolder holder) { 
    tutorialRunnable.setRunning(false); 
    while (thread != null) { 
     try { 
      thread.join(); 
      thread = null; 
     } catch (InterruptedException e) { 
     } 
    } 
} 

Ngoài ra, dựa vào ngoại lệ là biểu mẫu xấu. Điều đó nên được sử dụng như một phương sách cuối cùng khi mã của riêng bạn hoạt động bất ngờ.

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