Truy cập trình xử lý chuỗi giao diện người dùng từ một dịch vụ


89

Tôi đang thử một số thứ mới trên Android mà tôi cần truy cập trình xử lý của chuỗi giao diện người dùng.

Tôi biết những điều sau:

  1. Chuỗi giao diện người dùng có trình xử lý và trình lặp của riêng nó
  2. Mọi thông báo sẽ được đưa vào hàng đợi thông báo của chuỗi giao diện người dùng
  3. Bộ lặp chọn sự kiện và chuyển nó cho bộ xử lý
  4. Trình xử lý xử lý thông báo và gửi sự kiện cụ thể đến giao diện người dùng

Tôi muốn có dịch vụ của mình, dịch vụ này phải lấy trình xử lý chuỗi giao diện người dùng và đưa thông báo vào trình xử lý này. Vì vậy, thông báo này sẽ được xử lý và sẽ được cấp cho giao diện người dùng. Ở đây, dịch vụ sẽ là một dịch vụ bình thường sẽ được khởi động bởi một số ứng dụng.

Tôi muốn biết nếu điều này là có thể. Nếu vậy, vui lòng đề xuất một số đoạn mã để tôi có thể thử.

Kính trọng Girish

Câu trả lời:


179

Đoạn mã này tạo một Trình xử lý được liên kết với chuỗi (Giao diện người dùng) chính:

Handler handler = new Handler(Looper.getMainLooper());

Sau đó, bạn có thể đăng nội dung để thực thi trong chuỗi chính (UI) như sau:

handler.post(runnable_to_call_from_main_thread);

Nếu chính trình xử lý được tạo từ luồng chính (UI), đối số có thể bị bỏ qua cho ngắn gọn:

Handler handler = new Handler();

Các Android Dev Hướng dẫn về quy trình và chủ đề có thêm thông tin.


2
Đã thử nghiệm nó và nó hoạt động tuyệt vời! Ví dụ về trường hợp sử dụng: Tôi có một giao diện web đang được cung cấp bởi một máy chủ chạy trực tiếp trên thiết bị. Vì giao diện có thể được sử dụng để tương tác trực tiếp với giao diện người dùng và vì máy chủ cần chạy trên chuỗi của chính nó, tôi cần một cách để chạm vào chuỗi giao diện người dùng từ bên ngoài Hoạt động. Phương pháp bạn đã mô tả hoạt động rất hiệu quả.
mrPjer

1
Xuất sắc. Hoạt động như một sự quyến rũ, và rất hữu ích. CẢM ƠN BẠN.
JRun

hoàn hảo ^^ vừa mới sử dụng nó để cập nhật ui của tôi từ StreamingService. chính xác những gì tôi cần cảm ơn!
An-droid

bạn có biết liệu tôi có thể tạo một phiên bản singleton của một trình xử lý và sử dụng nó mỗi khi tôi cần chạy một cái gì đó trên luồng ui không?
HelloWorld

Tôi đoán chúng ta sẽ không bao giờ biết
Denny

28

Tạo một Messengerđối tượng gắn liền với của bạn Handlervà chuyển đối tượng đó Messengervào Service(ví dụ: trong phần Intentbổ sung cho startService()). Sau Serviceđó có thể gửi một Messageđến Handlerqua Messenger. Đây là một ứng dụng mẫu chứng minh điều này.


Cảm ơn vì mẹo này. Điều này rất hữu ích. Vui lòng xem ngăn xếp sau để biết luồng sự kiện chạm vào dòng hoạt động của tôi MyDemo.dispatchTouchEvent (MotionEvent): 20 PhoneWindow $ DecorView.dispatchTouchEvent (MotionEvent) dòng: 1696 ViewRoot.handleMessage (Message) dòng: 1658 ViewRoot (Handler) .dispatchMessage (Message ) dòng: 99 Dòng Looper.loop (): 123 // Xử lý sự kiện bắt đầu tại đây Dòng ActivityThread.main (String []): 4203 Ở đây ViewRoot là một Trình xử lý. Tôi muốn lấy tham chiếu của trình xử lý này ... có thể lấy nó từ ứng dụng của tôi không?
iLikeAndroid

@iLikeAndroid: Nếu bạn không tạo Handler, bạn không thể truy cập nó, AFAIK.
CommonsWare

Cảm ơn bạn. Tôi đã cố gắng tạo một phiên bản của ViewRoot. Đây không là gì ngoài một người xử lý. Bây giờ tôi có thể đưa ra các thông báo trên trình xử lý này. Trình xử lý đang nhận được tin nhắn. Nhưng ViewRoot không thể xử lý thông báo vì nó không được khởi tạo đúng cách. Tôi cần gọi ViewRoot.setView () để khởi tạo dữ liệu thích hợp cho ViewRoot. Tôi muốn biết có chế độ xem mặc định hay chế độ xem cơ sở, v.v. mà tôi có thể sử dụng để khởi tạo không?
iLikeAndroid

@iLikeAndroid: Không có ViewRoottrong SDK Android, AFAICT.
CommonsWare

1
@ hadez30: Cá nhân tôi không sử dụng các dịch vụ ràng buộc nhiều. Bạn vẫn được hoan nghênh sử dụng a Handler/ Messenger, mặc dù tôi sẽ thay thế tất cả điều đó bằng một bus sự kiện (ví dụ: EventBus của greenrobot).
CommonsWare

4

Hiện tại, tôi thích sử dụng thư viện bus sự kiện như Otto cho loại vấn đề này. Chỉ cần đăng ký các thành phần mong muốn (hoạt động):

protected void onResume() {
    super.onResume();
    bus.register(this);
}

Sau đó, cung cấp một phương thức gọi lại:

public void onTimeLeftEvent(TimeLeftEvent ev) {
    // process event..
}

và sau đó khi dịch vụ của bạn thực thi một câu lệnh như sau:

bus.post(new TimeLeftEvent(340));

POJO đó sẽ được chuyển cho hoạt động trên của bạn và tất cả các thành phần đăng ký khác. Đơn giản và thanh lịch.


3

Tôi khuyên bạn nên thử mã sau:

    new Handler(Looper.getMainLooper()).post(() -> {

        //UI THREAD CODE HERE



    });

Cần có một số giải thích bổ sung để hỗ trợ OP.
Moog

2

Bạn có thể nhận các giá trị thông qua bộ thu phát sóng ...... như sau, Đầu tiên hãy tạo IntentFilter của riêng bạn như sau,

Intent intentFilter=new IntentFilter();
intentFilter.addAction("YOUR_INTENT_FILTER");

Sau đó, tạo BroadcastReceiver lớp bên trong như,

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    /** Receives the broadcast that has been fired */
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction()=="YOUR_INTENT_FILTER"){
           //HERE YOU WILL GET VALUES FROM BROADCAST THROUGH INTENT EDIT YOUR TEXTVIEW///////////
           String receivedValue=intent.getStringExtra("KEY");
        }
    }
};

Bây giờ Đăng ký bộ thu Broadcast của bạn trong onResume () với tư cách,

registerReceiver(broadcastReceiver, intentFilter);

Và cuối cùng Hủy đăng ký BroadcastReceiver trong onDestroy () với tư cách,

unregisterReceiver(broadcastReceiver);

Bây giờ là phần quan trọng nhất ... Bạn cần kích hoạt chương trình phát sóng từ bất cứ nơi nào bạn cần gửi các giá trị ..... vì vậy hãy làm như,

Intent i=new Intent();
i.setAction("YOUR_INTENT_FILTER");
i.putExtra("KEY", "YOUR_VALUE");
sendBroadcast(i);

.... chúc mừng :)


1

Trong kotlin cách bạn có thể làm điều đó

Giả sử nếu bạn muốn hiển thị tin nhắn Toast từ dịch vụ

val handler = Handler(Looper.getMainLooper())
handler.post {
   Toast.makeText(context, "This is my message",Toast.LENGTH_LONG).show()
}

0

Giải pháp:

  1. Tạo một trình xử với Looper từ chính Chủ đề: RequestHandler
  2. Tạo một Handlervới Loopertừ Main Thread: responseHandler và ghi đèhandleMessage phương thức
  3. đăng một Runnable tác vụ trên requestHandler
  4. Phía trong Runnable vụ , gọi sendMessage trên responseHandler
  5. Điều này sendMessageKết quả gọi ra hàm xử lý trong responseHandler.
  6. Nhận các thuộc tính từ Messagevà xử lý nó, cập nhật giao diện người dùng

Mã mẫu:

    /* Handler from UI Thread to send request */

    Handler requestHandler = new Handler(Looper.getMainLooper());

     /* Handler from UI Thread to process messages */

    final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {

            /* Processing handleMessage */

            Toast.makeText(MainActivity.this,
                    "Runnable completed with result:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

    for ( int i=0; i<10; i++) {
        Runnable myRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                   /* Send an Event to UI Thread through message. 
                      Add business logic and prepare message by 
                      replacing example code */

                    String text = "" + (++rId);
                    Message msg = new Message();

                    msg.obj = text.toString();
                    responseHandler.sendMessage(msg);
                    System.out.println(text.toString());

                } catch (Exception err) {
                    err.printStackTrace();
                }
            }
        };
        requestHandler.post(myRunnable);
    }
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.