2011-10-13 42 views
21

Tôi cần cập nhật một số giao diện người dùng và thực hiện bên trong chuỗi giao diện người dùng bằng cách sử dụng runOnUiThread
Bây giờ, dữ liệu cho giao diện người dùng đến từ Chủ đề khác, được đại diện bởi data tại đây.
Android - cách chuyển dữ liệu đến Runnable trong runOnUiThread?

Làm cách nào tôi có thể chuyển dữ liệu đến Runnable, để chúng có thể được sử dụng để cập nhật giao diện người dùng? Android dường như không cho phép sử dụng dữ liệu trực tiếp. Có một cách thanh lịch để làm điều này?

public void OnNewSensorData(Data data) { 

    runOnUiThread(new Runnable() { 
     public void run() { 
      //use data 
     } 
    }); 
} 

Giải pháp của tôi đã tạo ra một fioeld private Data sensordata bên trong của runnable và gán dữ liệu cho nó. Điều này chỉ hoạt động, nếu bản gốc Data data là cuối cùng.

public void OnNewSensorData(final Data data) { 

    runOnUiThread(new Runnable() { 
     private Data sensordata = data; 
     public void run() { 
      //use sensordata which is equal to data 
     } 
    }); 
} 

Trả lời

35

Vấn đề bạn thấy là

lớp Inner trong chụp Java ("đóng toàn bộ") các từ vựng phạm vi trong đó chúng được xác định. Nhưng họ chỉ nắm bắt các biến được khai báo "cuối cùng".

Nếu đây là rõ ràng như bùn, có một cuộc thảo luận tốt về các chi tiết ở đây: Cannot refer to a non-final variable inside an inner class defined in a different method

Nhưng giải pháp của bạn có vẻ tốt đẹp.Bên cạnh đó, với điều kiện là data là cuối cùng, bạn có thể đơn giản hóa mã này:

public void OnNewSensorData(final Data data) { 
    runOnUiThread(new Runnable() { 
     public void run() { 
      // use data here 
      data.doSomething(); 
     } 
    }); 
} 
1

Bạn sẽ cần phải cập nhật mỗi khi chương trình của bạn có Data mới mà chương trình muốn hiển thị. Danh sách mã thứ hai của bạn ở đây là cách tiêu chuẩn để thực hiện việc này. Có thể có một số bắt nếu bạn tiếp tục cập nhật Data trong chuỗi. Nếu trường hợp này xảy ra, hãy cân nhắc việc chặn luồng cho đến khi giao diện người dùng kết thúc cập nhật hoặc sao chép dữ liệu sang đối tượng Data khác.

Điều đang xảy ra bên trong là JVM đang sao chép tham chiếu đến đối tượng Data khi lớp ẩn danh sẽ chạy. Data được lưu trữ bên trong vẫn có thể được thay đổi. Nếu phương pháp của bạn yêu cầu thay đổi bổ sung cho Data, chỉ cần sử dụng một biến khác (tham chiếu đối tượng) chẳng hạn như: final Data finalData = data;. Bạn cũng có thể xóa dòng private Data sensordata = data; và sử dụng dữ liệu trực tiếp trong phương thức chạy của mình.

Nó có thể không có vẻ thanh lịch nhưng đây là cách Java chuyển các biến đối tượng đến các lớp ẩn danh. Có cú pháp mới trong ngôn ngữ Java phiên bản 7 nhưng Android tương thích với ngôn ngữ Java phiên bản 5 và 6.

20

Nếu bạn muốn tránh sử dụng một biến thức trung gian (như mô tả bởi Dan S), bạn có thể thực hiện Runnable với một phương pháp bổ sung để thiết lập dữ liệu:

public class MyRunnable implements Runnable { 
    private Data data; 
    public void setData(Data _data) { 
    this.data = _data; 
    } 

    public void run() { 
    // do whatever you want with data 
    } 
} 

sau đó, bạn có thể gọi phương thức như thế này:

public void OnNewSensorData(Data data) { 
    MyRunnable runnable = new MyRunnable(); 
    runnable.setData(data); 
    runOnUiThread(runnable); 
} 

bạn cũng có thể làm cho constructor MyRunnable lấy trong Đạt một ví dụ làm đối số:

public class MyRunnable implements Runnable { 
    private Data data; 
    public MyRunnable(Data _data) { 
    this.data = _data; 
    } 

    public void run() { 
    ... 
    } 
} 

và sau đó chỉ cần nói runOnUiThread (new MyRunnable (data));

0
public static Activity globalContext = null;  
CommonSetting.globalContext = this;// put this in MainACtivity.onCreate() 
public void createToastShort(final String message) { 
    runOnUiThread(new Runnable() { 
     public void run() { 
     Toast.makeText(CommonSetting.globalContext, message, Toast.LENGTH_SHORT).show(); 
     } 
    }); 
} 
5

Tôi gặp sự cố tương tự khi tôi muốn chuyển thông tin vào chuỗi. Để giải quyết nó với hệ thống android, tôi thay đổi câu trả lời corsiKa tại: Runnable with a parameter?

Bạn có thể khai báo một đúng lớp trong phương pháp này và vượt qua param như hình dưới đây:

void Foo(String str) { 
    class OneShotTask implements Runnable { 
     String str; 
     OneShotTask(String s) { str = s; } 
     public void run() { 
      someFunc(str); 
     } 
    } 
    runOnUiThread(new OneShotTask(str)); 
} 
1

Đây là một trường hợp điển hình mà dịch vụ callback được gọi để cập nhật một chuỗi trạng thái UI (TextView textStatus). Dịch vụ có thể được tạo luồng.

Các mẫu kết hợp kiểm tra nếu chủ đề chuyển hướng là cần thiết và chuyển hướng thực tế:

// service callbacks 
    public void service_StatusTextChanged(final String s) { 
     if(isOnUiThread()) { 
      textStatus.setText(s); 
     } else { 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        textStatus.setText(s); 
       } 
      }); 
     } 
    } 

    static public boolean isOnUiThread() { 
     return Thread.currentThread() == Looper.getMainLooper().getThread(); 
    } 

Xem thêm How to check if running on UI thread in Android?

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