Khi nào thì đăng ký / hủy đăng ký bộ thu phát sóng được tạo trong một hoạt động?


79

Tôi có nhu cầu tạo bộ thu phát sóng tùy chỉnh trong sự kiện onCreate của một hoạt động và rõ ràng là tôi cần phải hủy Đăng ký bộ thu phát sóng trong sự kiện onDestroy của hoạt động

Để rõ ràng đây là một đ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 nên đăng ký và hủy đăng ký bộ thu phát sóng.

Tôi thực sự muốn hiểu điều gì được coi là phương pháp tốt nhất cho việc này và tại sao.


Đó là bởi vì khi onDestroy()được gọi không còn các sự kiện sẽ được người nhận lắng nghe.
de_billa_

Câu trả lời:


91

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

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

Nếu bạn muốn nhận các sự kiện truyền phát trong nền, bạn nên xem xét sử dụng một dịch vụ như được chỉ ra ở đây .

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


3
Bạn có gợi ý rằng tôi đăng ký onResume INSTEAD của onCreate hay không? OnResume có luôn được gọi khi một hoạt động được tạo không?
jamesc

9
Bạn nên đăng ký onResume vâng, onResume () luôn được gọi khi hoạt động được hiển thị (đây 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 ( developer.android.com/reference/android/app/Activity.html ) nếu bạn chỉ đăng ký onCreate () và hủy đăng ký onPause (), sau đó vào lần tiếp theo hoạt động được đưa lên nền trước, onCreate () sẽ không được gọi lại và sau đó nó sẽ không đăng ký lại người nhận. Và đúng vậy, ý tôi là INSTEAD của, không thực hiện trênCreate ().
SnowyTracks

1
@SnowyTracks: bạn có thể nhận xét tại sao lại thích thực hiện các lệnh gọi đăng ký BroadcastReceiver trong onResume / onPause hơn là onStart / onStop? Xem qua hướng dẫn dành cho nhà phát triển cho các dịch vụ ràng buộc, tôi tìm thấy điều này . Ở phần cuối của phần này, bạn nên thực hiện ràng buộc / hủy liên kết dịch vụ trong onStart / onStop thay vì onResume / onPause (vì lý do hiệu suất). Tôi tự hỏi nếu điều này cũng áp dụng cho BroadcastReceivers? Cảm ơn trước.
Janus Varmarken

1
@jvmk Đồng ý, tài liệu Android nói làm điều này trong onStart và onStop, tôi nghĩ rằng trong 99% trường hợp, nó tạo ra rất ít khác biệt, chỉ có sự khác biệt về hành vi là các hoạt động hộp thoại hoặc một phần hoạt động tiền cảnh được sử dụng. Nhưng tôi sẽ cập nhật câu trả lời của mình để phù hợp với tài liệu Android
SnowyTracks

1
Tôi thấy bạn đã chỉnh sửa đoạn thứ 2 ngày hôm qua ... cảm ơn vì đã nỗ lực để có một câu trả lời nhất quán hơn. Nhưng nó vẫn không giải thích tại sao người ta nên sử dụng onStart / onStop thay vì hoặc kết hợp với onResume / onPause , đó là câu hỏi của OP. Thay vào đó, lời giải thích của đoạn thứ 2 cũng đúng với onResume / onPause cũng như onStart / onStop: khi onPause được gọi, hoạt động không còn ở phía trước. Vì vậy, chúng tôi không có "lý do tại sao" cho đề xuất của bạn.
LarsH

19

Như onDestroy()không được đảm bảo để được gọi, bạn sẽ sử dụng onPause()để hủy đăng ký. Xem xét vòng đời của bộ 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 ở phía trước? Sau đó sử dụng onResume()/onPause()


Điều gì sẽ xảy ra nếu chúng tôi vẫn cần cập nhật nội dung trong hoạt động ngay cả khi hoạt động ở chế độ nền, vì người dùng có thể tiếp tục ứng dụng và dữ liệu cập nhật sẽ được hiển thị trong trường hợp đó?
Usman Rana

9

Tài liệu Android không quy định một nơi duy nhất để đăng ký / hủy đăng ký bộ thu phát sóng, nhưng nó đề cập đến cả onStart()/ onStop()onResume()/ onPause()như các khả năng.

Yếu tố lớn nhất trong việc đưa ra quyết định này là, khi nào bộ thu của bạn cần có thể thực hiện công việc của nó? Đ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ì đó đối với chương trình phát sóng chỉ khi hoạt động được tập trung vào không? Nếu vậy, bạn có thể đăng ký / hủy đăng ký nó trong onPause()/ onReceive(). (Bạn cũng có thể sử dụng thời gian tồn tại lâu hơn, chẳng hạn như onStart()/ onStop(), nhưng sau đó bạn nên kiểm tra onReceive()xem hoạt động có được lấy nét trong quá trình thu của máy thu hay không.)

  • Người nhận có cần phải làm gì đó khi hiển thị, ngay cả khi nó không có tiêu điểm (ví dụ: khi hộp thoại đang được hiển thị)? Nếu vậy, hãy sử dụng onStart()/ onStop()(hoặc thời gian sử dụng lâu hơn, nhưng một lần nữa, người nhận onReceive()phải 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ó cần phải nhớ rằng điều gì đó đã xảy ra, để khi hoạt động trở nên rõ ràng, nó có thể phản ánh tình trạng kết quả của sự việc không? Sau đó, bạn cần sử dụng onCreate()/ onDestroy()để đăng ký / hủy đăng ký. (Lưu ý rằng có những cách khác để triển khai loại chức năng này.)

Nếu bạn đăng ký onStart(), cũng đừng đăng ký họ onResume(), bởi vì điều đó sẽ là thừa: onResume()không bao giờ được gọi mà không onStart()được gọi trước.

Ngoài ra, hãy nhớ rằng tốt nhất là giữ onPause () càng nhẹ càng tốt :

Quá trình thực thi onPause () rất ngắn và không nhất thiết có đủ thời gian để thực hiện các thao tác lưu. Vì lý do này, bạn không nên sử dụng onPause () để lưu dữ liệu ứng dụng hoặc người dùng, thực hiện 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 đó có thể không hoàn thành trước khi phương thức hoàn thành. Thay vào đó, bạn nên thực hiện các thao tác tắt tải nặng trong onStop ().

Đúng onDestroy()không đảm bảo sẽ được gọi 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 bị ngắt, quá trình sẽ không nhận được các chương trình phát sóng. Trong trường hợp đó, có thực sự cần thiết phải hủy đăng ký các thiết bị thu phát sóng không?


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 khó hiểu và không hoàn toàn chính xác. Bạn nói If you register in onStart(), don't also register them in onPause(), because that would be redundant: onPause() is never called without onStart() being called first.chỉ là phi logic 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

@jamesc: Rất tiếc, ý tôi là onResume hơn là onPause. Bạn nói đúng, điều đó hơi khó hiểu. Đã sửa ngay. Đối với câu trả lời được chấp nhận, tôi đã bình luận về nó. Tôi tin rằng câu trả lời này bổ sung thông tin quan trọng và có liên quan mà câu trả lời được chấp nhận không cung cấp.
LarsH

5

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


1
Tôi cũng đang làm điều này. Vấn đề đã có với onStop()là tốt
Vygintas B

0

Bạn nên đăng ký và hủy đăng ký chương trình phát sóng của mình trong các phương thức onResume () và onPause ().

nếu bạn đăng ký onStart () và hủy đăng ký trong onStop (). thời gian đó bạn sẽ nhận được vấn đề sau.

nếu màn hình thiết bị của bạn đang khóa thì thời gian onStop () được gọi và nếu bạn mở khóa thì thời gian onStart () sẽ không bao giờ được gọi. đó là lý do tại sao bạn đăng ký và hủy đăng ký nó trong các phương thức onResume () và onPause ().

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.