2010-03-18 34 views
37

Tôi đang cố tạo một ứng dụng Android đơn giản có Danh sách hoạt động thông tin, khi ứng dụng bắt đầu, tôi dự định bắt đầu Dịch vụ sẽ liên tục tính toán dữ liệu (nó sẽ thay đổi) và tôi muốn ActivityList được đồng bộ với dữ liệu mà dịch vụ đang tính toán cho tuổi thọ của ứng dụng.Làm cách nào để cập nhật thông tin trong Hoạt động Android từ Dịch vụ nền

Tôi làm cách nào để thiết lập Hoạt động của mình để nghe Dịch vụ? Đây có phải là cách tốt nhất để tiếp cận vấn đề này không? Ví dụ, nếu bạn tưởng tượng một danh sách giá cổ phiếu - dữ liệu sẽ được thay đổi thường xuyên và cần phải được đồng bộ hóa với (trong trường hợp của tôi) Dịch vụ đang tính toán/tìm nạp dữ liệu liên tục.

Cảm ơn trước

Trả lời

91

Tôi làm cách nào để thiết lập Hoạt động của mình là nghe Dịch vụ? Đây có phải là cách tốt nhất để tiếp cận vấn đề này không?

Bạn có ba tùy chọn quan trọng, như tôi nhìn thấy nó:

  1. Polling. Activity định kỳ yêu cầu Service để có dữ liệu mới nhất. IMHO, tùy chọn này hút, nhưng nó chắc chắn có thể.

  2. Gọi lại. Câu trả lời của mỗi câu trả lời, số Activity đăng ký một đối tượng gọi lại ("người quan sát") với Service. Service gọi phương thức trên cuộc gọi lại khi dữ liệu thay đổi, lần lượt cập nhật giao diện người dùng. Bạn có thể xem ví dụ về việc sử dụng điều đó với Servicehere.

  3. Phát sóng Intents. Việc phát Service phát sóng Intent qua sendBroadcast() khi thay đổi dữ liệu. Activity đăng ký BroadcastReceiver sử dụng registerReceiver() và rằng BroadcastReceiver được thông báo về chương trình phát sóng đến. Điều này kích hoạt Activity để tải dữ liệu mới nhất từ ​​Service, hoặc có thể chỉ để có được dữ liệu mới nhất trong số các tính năng bổ sung trong chương trình phát sóng Intent.Bạn có thể xem ví dụ về cách sử dụng kỹ thuật đó với Servicehere.

+11

Ví dụ tuyệt vời về số 3 ở đây ... http://www.websmithing.com/2011/02/01/how-to-update-the-ui-in-an-android-activity-using-data-from- a-background-service/ –

+1

Nếu tôi đóng ứng dụng thì sao. Làm cách nào tôi có thể xử lý trường hợp chạy AlarmManager bằng Hoạt động trạng thái. – Basbous

+2

Ưu và nhược điểm của kỹ thuật 2 và 3 là gì? –

4

Âm thanh này giống như một ứng cử viên tốt cho Mẫu quan sát viên. Về cơ bản hoạt động của bạn (The Observer) sẽ tự đăng ký với dịch vụ nền (The Observable) và bạn có thể đẩy hoặc kéo dữ liệu từ Activity của bạn. Người quan sát của bạn trong trường hợp này sẽ là Hoạt động của bạn và Đài quan sát sẽ là Dịch vụ của bạn.

Nếu bạn không biết gì về Mẫu thiết kế mua "Mẫu thiết kế đầu tiên", nó rất dễ đọc và có đầy đủ thông tin tuyệt vời.

PS: Tôi đang đọc nó ngay bây giờ.

+8

Bạn nói đúng nhưng câu trả lời này không có cách nào khác ... – Janusz

0

Bạn sẽ chạy một chuỗi nền để tính toán các thay đổi trong danh sách. Chủ đề này bây giờ cần một khả năng để thông báo cho GUI rằng danh sách đã được cập nhật.

Bạn có thể sử dụng một số loại ArrayAdapter để lấy dữ liệu vào ListView. ArrayAdapter có một phương thức được gọi là adpater.notifyDataSetChanged() mỗi khi bạn gọi phương thức này, bộ điều hợp sẽ thấy rằng dữ liệu tương ứng đã thay đổi và sau đó thông báo cho listview rằng nó sẽ cập nhật ở khả năng tiếp theo.

+2

Tốt hơn, nếu bạn định sử dụng 'ArrayAdapter', chỉ cần gọi' add() ',' insert() 'và' remove() 'phương thức trên' ArrayAdapter' để thay đổi nội dung của nó. Bạn không cần 'notifyDataSetChanged()' sau đó. – CommonsWare

0

Bạn cần sử dụng bindService() để liên kết hoạt động với dịch vụ đang chạy và liên lạc với nó.

public class BindingActivity extends Activity { 
YourService mService; 
boolean mBound = false; 

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

@Override 
protected void onStart() { 
    super.onStart(); 
    // Bind to Your Service 
    Intent intent = new Intent(this, YourService.class); 
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
} 

@Override 
protected void onStop() { 
    super.onStop(); 
    // Unbind from the service 
    if (mBound) { 
     unbindService(mConnection); 
     mBound = false; 
    } 
} 

/** Called when a button is clicked (the button in the layout file attaches to 
    * this method with the android:onClick attribute) */ 
public void onButtonClick(View v) { 
    if (mBound) { 
     // Call a method from your Service. 
     // However, if this call were something that might hang, then this request should 
     // occur in a separate thread to avoid slowing down the activity performance. 
     int num = mService.getRandomNumber(); 
     Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); 
    } 
} 

/** Defines callbacks for service binding, passed to bindService() */ 
private ServiceConnection mConnection = new ServiceConnection() { 

    @Override 
    public void onServiceConnected(ComponentName className, 
      IBinder service) { 
     // We've bound to the running Service, cast the IBinder and get instance 
     LocalBinder binder = (LocalBinder) service; 
     mService = binder.getService(); 
     mBound = true; 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName arg0) { 
     mBound = false; 
    } 
}; 
} 

và dịch vụ của bạn như:

public class LocalService extends Service { 
    // Binder given to clients 
    private final IBinder mBinder = new LocalBinder(); 
    // Random number generator 
    private final Random mGenerator = new Random(); 

/** 
* Class used for the client Binder. Because we know this service always 
* runs in the same process as its clients, we don't need to deal with IPC. 
*/ 
public class LocalBinder extends Binder { 
    LocalService getService() { 
     // Return this instance of LocalService so clients can call public methods 
     return LocalService.this; 
    } 
} 

@Override 
public IBinder onBind(Intent intent) { 
    return mBinder; 
} 

/** method for clients */ 
public int getRandomNumber() { 
    return mGenerator.nextInt(100); 
    } 
} 
+0

Đây không phải là điều mà OP yêu cầu. Mặc dù điều này có thể hoạt động (Dịch vụ liên tục cập nhật dữ liệu và giao diện người dùng có thể yêu cầu dữ liệu mới), nó yêu cầu cuộc gọi từ phía giao diện người dùng như phản ứng với đầu vào của người dùng (như nút bấm). Câu hỏi ngược lại yêu cầu một cách để giao diện người dùng cập nhật liên tục với dữ liệu mới trong Dịch vụ. –

0

Tôi thực sự, thực sự tự hỏi tại sao không ai đề cập đến một phương pháp đơn giản sử dụng một EventBus bởi bất cứ điều gì thư viện. Đây là khóa học nếu bạn không sử dụng RX. Yêu thích cá nhân của tôi là EventBus bởi GreenRobot. https://github.com/greenrobot/EventBus

Chỉ với một vài dòng mã và không có giao diện. Kích hoạt một sự kiện và lắng nghe nó ở bất cứ đâu bạn muốn. Nó được tách ra, nó là chủ đề an toàn và nó sẽ không làm hỏng ứng dụng của bạn.

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