2011-10-25 10 views
63

Tôi có nhu cầu tạo bộ thu phát quảng cáo tùy chỉnh trong sự kiện onCreate của hoạt động và rõ ràng là tôi cần hủy đăng ký bộ thu phát sóng trong sự kiện onDestroy của hoạt độngAndroid - Khi nào cần đăng ký/Hủy đăng ký người nhận phát sóng được tạo trong một hoạt động?

Để rõ ràng đây là đoạn mã tôi sử dụng

public class AnActivity extends Activity { 
    private ResponseReceiver receiver; 

    public class ResponseReceiver extends BroadcastReceiver { 
      public static final String ACTION_RESP = 
       "mypackagename.intent.action.MESSAGE_PROCESSED"; 

      @Override 
      public void onReceive(Context context, Intent intent) { 
// TODO Start a dialogue if message indicates successfully posted to server 
      } 
    } 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP); 
     filter.addCategory(Intent.CATEGORY_DEFAULT); 
     receiver = new ResponseReceiver(); 
     registerReceiver(receiver, filter); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     unregisterReceiver(receiver); 
    } 

Tôi đã đọc rằng các sự kiện onPause/onResume và onStart/onStop cho hoạt động cũng phải đăng ký và hủy đăng ký bộ thu phát sóng.

Tôi thực sự muốn hiểu những gì được coi là thực tiễn tốt nhất cho điều này và tại sao.

Trả lời

75

Bạn nên đăng ký và hủy đăng ký người nhận onStart()onStop().

Lý do duy nhất mà Hoạt động đăng ký BroadcastReceiver s là sử dụng các sự kiện theo một cách nào đó vào hoạt động hiện tại, để thông báo cho Người dùng về sự kiện. Nếu onStop() đã được gọi, thì Activity không còn ở mặt trước và do đó không thể cập nhật Người dùng.

Nếu bạn muốn nhận sự kiện phát sóng dưới nền, bạn nên cân nhắc sử dụng dịch vụ như được nêu rõ here.

Giống như Konstantin nói, onDestroy() không được bảo đảm để được gọi và bạn có thể tiếp tục nhận chương trình phát sóng trong một thời gian dài, khi Activity không còn mở.

+3

Bạn có đề xuất rằng tôi đăng ký trong onResume INSTEAD của onCreate hoặc cũng như không? OnResume có được gọi khi hoạt động được tạo không? – jamesc

+7

Bạn nên đăng ký onResume yes, onResume() luôn được gọi trên hoạt động đang được hiển thị (đó là phương thức cuối cùng được gọi trước khi hoạt động của bạn xuất hiện (http://developer.android.com/reference/android/app/Activity.html) nếu bạn chỉ đăng ký onCreate() và unregister onPause(), thì lần sau hoạt động được đưa tới foreground, onCreate() sẽ không được gọi lại và sau đó nó sẽ không đăng ký lại người nhận. không làm điều đó onCreate() – SnowyTracks

+1

@SnowyTracks: bạn có thể bình luận về lý do tại sao nó thích hợp hơn để thực hiện các cuộc gọi đăng ký BroadcastReceiver trong onResume/onPause thay vì onStart/onStop? Xem qua hướng dẫn dành cho nhà phát triển cho các dịch vụ bị ràng buộc, tôi thấy [this] (http : //developer.android.com/guide/components/bound-services.html#Binding) Ở phần cuối của phần này, bạn nên thực hiện ràng buộc/đóng gói dịch vụ trong onStart/onStop thay vì onResume/onPause (để thực hiện lý do). tự hỏi nếu điều này cũng áp dụng cho BroadcastReceivers? Cảm ơn trước. –

18

onDestroy() không được bảo đảm để được gọi, bạn sẽ sử dụng onPause() để hủy đăng ký. Xem xét vòng đời của máy thu phát sóng của bạn: Bạn có cần nó hoạt động không, chỉ khi hoạt động của bạn ở tiền cảnh? Sau đó, sử dụng onResume()/onPause()

4

Android có thể giết ứng dụng của bạn bằng cách bỏ phương thức onStop(). Cách tốt nhất để giải quyết tình huống đó là đăng ký BroadcastReceiver theo phương thức onResume() và hủy đăng ký trong onPause().

+0

Tôi cũng đang làm điều này. Đã có vấn đề với 'onStop()' aswell –

4

Tài liệu Android không quy định một nơi duy nhất để đăng ký/thu phát sóng unregister, nhưng it mentions cả onStart()/onStop()onResume()/onPause() như khả năng.

Yếu tố lớn nhất trong việc đưa ra quyết định này là khi nào người nhận của bạn cần có khả năng thực hiện công việc của mình? Điều này sẽ xác định thời điểm đăng ký và hủy đăng ký.

  • Người nhận có cần thực hiện điều gì đó về phát sóng khi hoạt động được lấy nét không? Nếu có, bạn có thể đăng ký/hủy đăng ký nó trong onPause()/onReceive(). (Bạn cũng có thể sử dụng một đời còn như onStart()/onStop(), nhưng sau đó bạn nên kiểm tra trong thời gian người nhận onReceive() liệu hoạt động được lấy nét.)

  • Có người nhận cần phải làm điều gì đó khi nhìn thấy được, ngay cả khi nó doesn không tập trung (ví dụ như khi một hộp thoại đang được hiển thị)? Nếu vậy, hãy sử dụng onStart()/onStop() (hoặc tuổi thọ dài hơn, nhưng một lần nữa, người nhận onReceive() nên kiểm tra xem hoạt động có hiển thị hay không).

  • Người nhận có cần biết về chương trình phát sóng ngay cả khi hoạt động không hiển thị không? Ví dụ, nó cần phải nhớ rằng một cái gì đó đã xảy ra, để khi các hoạt động trở thành có thể nhìn thấy, nó có thể phản ánh trạng thái kết quả của công việc? Sau đó, bạn cần sử dụng onCreate()/onDestroy() để đăng ký/hủy đăng ký. (Lưu ý có những cách khác để thực hiện các loại chức năng.)

Nếu bạn đăng ký trong onStart(), không còn đăng ký chúng trong onResume(), vì đó sẽ là dư thừa: onResume() không bao giờ được gọi mà không onStart() được gọi Đầu tiên.

Cũng nên nhớ rằng nó là tốt nhất để keep onPause() as light as possible:

onPause() thực hiện là rất ngắn, và không cần phải có đủ đủ thời gian để thực hiện tiết kiệm hoạt động. Vì lý do này, bạn nên không sử dụng onPause() để lưu dữ liệu ứng dụng hoặc người dùng, thực hiện các cuộc gọi mạng hoặc thực hiện các giao dịch cơ sở dữ liệu; công việc như vậy có thể không hoàn thành trước khi phương thức hoàn tất. Thay vào đó, bạn nên thực hiện các thao tác tắt tải trong quá trình onStop().

Đúng là onDestroy()not guaranteed to be called nếu hệ thống giết quá trình của bạn để tiết kiệm bộ nhớ. Tuy nhiên, nếu quá trình này bị giết, quá trình này sẽ không nhận được chương trình phát sóng. Trong trường hợp đó, có thực sự cần thiết để hủy đăng ký người nhận phát sóng không?

+0

Cảm ơn bạn đã trả lời câu hỏi của tôi nhưng câu trả lời của bạn là khó hiểu và không chính xác nghiêm ngặt Bạn nói 'Nếu bạn đăng ký trong onStart(), cũng không đăng ký chúng trong onPause(), bởi vì đó sẽ là thừa: onPause() không bao giờ được gọi là không có onStart() được gọi là first.' chỉ là vô lý và khó hiểu, đặc biệt khi câu trả lời được chấp nhận là hoàn toàn chính xác. – jamesc

+0

@jamesc: Rất tiếc, tôi có nghĩa là onResume thay vì onPause. Bạn nói đúng, đó là một chút bối rối. Đã sửa lỗi. Đối với câu trả lời được chấp nhận, tôi đã nhận xét về nó. Tôi tin rằng câu trả lời này thêm thông tin quan trọng và có liên quan mà người được chấp nhận không cung cấp. – LarsH