Làm thế nào để xác định cuộc gọi lại trong Android?


152

Trong Google IO gần đây nhất, đã có một bài thuyết trình về việc triển khai các ứng dụng khách yên tĩnh. Thật không may, nó chỉ là một cuộc thảo luận cấp cao mà không có mã nguồn của việc thực hiện.

Trong sơ đồ này, trên đường dẫn trở lại có nhiều hàm gọi lại khác nhau cho các phương thức khác.

slide thuyết trình google io

Làm thế nào để tôi tuyên bố những phương pháp này là gì?

Tôi hiểu ý tưởng của một cuộc gọi lại - một đoạn mã được gọi sau khi một sự kiện nào đó đã xảy ra, nhưng tôi không biết làm thế nào để thực hiện nó. Cách duy nhất tôi đã thực hiện các cuộc gọi lại cho đến nay là ghi đè các phương thức khác nhau (ví dụ onActivityResult).

Tôi cảm thấy như tôi có một sự hiểu biết cơ bản về mẫu thiết kế, nhưng tôi tiếp tục bị vấp ngã về cách xử lý đường dẫn trở lại.


3
Chính xác những gì bạn cần. Tôi đang tìm kiếm điều tương tự và tình cờ thấy điều này: javaworld.com/javaworld/javatips/jw-javatip10.html
Sid

Câu trả lời:


218

Trong nhiều trường hợp, bạn có một giao diện và chuyển qua một đối tượng thực hiện nó. Các hộp thoại chẳng hạn có OnClickListener.

Chỉ là một ví dụ ngẫu nhiên:

// The callback interface
interface MyCallback {
    void callbackCall();
}

// The class that takes the callback
class Worker {
   MyCallback callback;

   void onEvent() {
      callback.callbackCall();
   }
}

// Option 1:

class Callback implements MyCallback {
   void callbackCall() {
      // callback code goes here
   }
}

worker.callback = new Callback();

// Option 2:

worker.callback = new MyCallback() {

   void callbackCall() {
      // callback code goes here
   }
};

Tôi có thể đã nhầm lẫn cú pháp trong tùy chọn 2. Đó là sớm.


5
Một ví dụ điển hình để hiểu rõ về kỹ thuật này là cách một đoạn nên giao tiếp với một đoạn khác thông qua hoạt động được chia sẻ Hoạt động: developer.android.com/guide/components/
trộm

Tôi cố gắng "thực hiện" giao diện MyCallback trong một hoạt động mới không thành công và hệ thống yêu cầu tôi chỉnh sửa đường dẫn nguồn trên đó. Vậy làm thế nào tôi có thể thực hiện "callBack" từ một hoạt động cũ sang một hoạt động mới?
Antoine Murion

3
Nó nói rằng biến gọi lại trong lớp worker là null đối với tôi
iYonatan

Ai đó có thể cho tương đương kotlin?
Tooniis

52

Khi có điều gì đó xảy ra trong tầm nhìn của tôi, tôi khởi động một sự kiện mà hoạt động của tôi đang lắng nghe:

// KHAI THÁC TẠI (TÙY CHỈNH) XEM

    private OnScoreSavedListener onScoreSavedListener;
    public interface OnScoreSavedListener {
        public void onScoreSaved();
    }
    // ALLOWS YOU TO SET LISTENER && INVOKE THE OVERIDING METHOD 
    // FROM WITHIN ACTIVITY
    public void setOnScoreSavedListener(OnScoreSavedListener listener) {
        onScoreSavedListener = listener;
    }

// KHAI THÁC TRONG HOẠT ĐỘNG

    MyCustomView slider = (MyCustomView) view.findViewById(R.id.slider)
    slider.setOnScoreSavedListener(new OnScoreSavedListener() {
        @Override
        public void onScoreSaved() {
            Log.v("","EVENT FIRED");
        }
    });

Nếu bạn muốn biết thêm về giao tiếp (cuộc gọi lại) giữa các đoạn, hãy xem tại đây: http://developer.android.com/guide/components/fragments.html#CransicatingWithActivity


1
Đó là hướng dẫn #CransicatingWithActivity thật tuyệt vời. Cuối cùng cũng hiểu cách sử dụng các cuộc gọi lại sau vài thử nghiệm.
Moise Jimenez

Câu trả lời chính xác. Cảm ơn!
iYonatan

Đơn giản và dễ hiểu. Cảm ơn!
Glenn J. Schworak

38

Không cần xác định giao diện mới khi bạn có thể sử dụng giao diện hiện có : android.os.Handler.Callback. Vượt qua một đối tượng của kiểu gọi lại và gọi các cuộc gọi lại handleMessage(Message msg).


Nhưng làm thế nào để làm điều đó?
Majurageerthan

26

Ví dụ để thực hiện phương thức gọi lại bằng giao diện.

Xác định giao diện, NewInterface.java .

gói javaapplication1;

public interface NewInterface {
    void callback();
}

Tạo một lớp mới, NewClass.java . Nó sẽ gọi phương thức gọi lại trong lớp chính.

package javaapplication1;

public class NewClass {

    private NewInterface mainClass;

    public NewClass(NewInterface mClass){
        mainClass = mClass;
    }

    public void calledFromMain(){
        //Do somthing...

        //call back main
        mainClass.callback();
    }
}

Lớp chính, JavaApplication1.java, để thực hiện giao diện Phương thức NewInterface - callback (). Nó sẽ tạo và gọi đối tượng NewClass. Sau đó, đối tượng NewClass sẽ lần lượt gọi lại phương thức gọi lại ().

package javaapplication1;
public class JavaApplication1 implements NewInterface{

    NewClass newClass;

    public static void main(String[] args) {

        System.out.println("test...");

        JavaApplication1 myApplication = new JavaApplication1();
        myApplication.doSomething();

    }

    private void doSomething(){
        newClass = new NewClass(this);
        newClass.calledFromMain();
    }

    @Override
    public void callback() {
        System.out.println("callback");
    }

}

1
Cho đến bây giờ chúng tôi đã sử dụng các giao diện để gọi lại nhưng bây giờ hình vuông đã phát triển một lib như xe buýt sự kiện Otto. Tôi thực sự nhanh hơn và hữu ích.
Amol Patil

20

để làm rõ một chút về câu trả lời của rồng (vì tôi phải mất một thời gian để tìm hiểu phải làm gì Handler.Callback):

Handlercó thể được sử dụng để thực hiện các cuộc gọi lại trong luồng hiện tại hoặc luồng khác, bằng cách chuyển nó Messages. các Messagetổ chức dữ liệu được sử dụng từ callback. a Handler.Callbackcó thể được chuyển cho người xây dựng Handlerđể tránh mở rộng Handler trực tiếp. do đó, để thực thi một số mã thông qua gọi lại từ luồng hiện tại:

Message message = new Message();
<set data to be passed to callback - eg message.obj, message.arg1 etc - here>

Callback callback = new Callback() {
    public boolean handleMessage(Message msg) {
        <code to be executed during callback>
    }
};

Handler handler = new Handler(callback);
handler.sendMessage(message);

EDIT: chỉ nhận ra có một cách tốt hơn để có được kết quả tương tự (trừ kiểm soát chính xác thời điểm thực hiện cuộc gọi lại):

post(new Runnable() {
    @Override
    public void run() {
        <code to be executed during callback>
    }
});

1
Bài đăng Runnable của bạn nằm trong phương thức handleMessage?
IgorGanapolsky

+1 cho câu trả lời tốt nhất. Tôi thích Callbackphiên bản này tốt hơn bởi vì bạn có thể không nhất thiết phải có quyền truy cập vào dữ liệu cần thiết Runnable.run()tại thời điểm bạn xây dựng nó
Kirby

Lưu ý: "Mặc dù hàm tạo của Message là công khai, cách tốt nhất để có được một trong số đó là gọi Message.obtain () hoặc một trong các phương thức Handler.obtainMessage () sẽ kéo chúng từ một nhóm các đối tượng tái chế." - từ đây
jk7

10

Bạn cũng có thể sử dụng LocalBroadcastcho mục đích này. Đây là một câu hỏi nhanh

Tạo một máy thu phát sóng:

   LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter("speedExceeded"));

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Double currentSpeed = intent.getDoubleExtra("currentSpeed", 20);
        Double currentLatitude = intent.getDoubleExtra("latitude", 0);
        Double currentLongitude = intent.getDoubleExtra("longitude", 0);
        //  ... react to local broadcast message
    }

Đây là cách bạn có thể kích hoạt nó

Intent intent = new Intent("speedExceeded");
intent.putExtra("currentSpeed", currentSpeed);
intent.putExtra("latitude", latitude);
intent.putExtra("longitude", longitude);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

unRegister nhận trong onPause:

protected void onPause() {
  super.onPause();
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
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.