在 Android 中使用接口回调

Using interface callbacks in Android

我目前正在尝试在 Android 上编写一个简单的聊天应用程序。

它获取语音,将其转换为文本,然后将其发送到服务器。

我希望能够使用 TextToSpeech 来读取服务器给出的响应。

我不断收到 java.lang.NullPointerException: Attempt to invoke interface method 'void {MYAPPNAME}.MyCallback.callbackCall()' on a null object reference。我看过其他有类似答案的问题,但它们相互矛盾,如他们所说 "the interface should be instantiated first" 或 "you don't instantiate interfaces" 等,让我感到困惑。

接收者:

public class MainActivity extends ActionBarActivity implements TextToSpeech.OnInitListener, MyCallback {
    ...

    private void sendToServer(String msg) {
        cThread = new ClientThread();
        cThread.msg = msg;
        Thread thread = new Thread(cThread);
        thread.start();
    }

    @Override
    public void callbackCall() {
        Log.d("CALLBACK", cThread.serverResponseSaved);
        // Do the speaking here.
    }
}

负责消息的实际代码:

interface MyCallback {
    public void callbackCall();
}

public class ClientThread implements Runnable {
    String address = "XXX.XXX.X.XX";
    int port = YYYYY;
    boolean connected = false;
    String msg = "";
    private String serverResponse;
    String serverResponseSaved;
    MyCallback callback;

    @Override
    public void run() {
        try {
            Socket socket = new Socket(address, port);
            this.connected = true;
            while(connected) {
                try {
                    PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
                    out.println(this.msg);
                    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        if ((serverResponse = in.readLine()) != null) {
                            serverResponseSaved = serverResponse;
                            Log.i("server says", serverResponseSaved);
                            callback.callbackCall();
                        }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            this.connected = false;
        }
    }
}

是我实现接口的方式不对吗?

编辑:

尝试通过以下方式实例化它: callback = new MyCallback(); 给我一个 'MyCallback is abstract. Cannot be instantiated.' 错误。

接口的使用基于: Here

您没有在任何地方设置 callback。您将其定义为 MyCallback 并为其命名 callback 但它仍然没有分配任何内容,因此当您点击 callback.callbackCall();

时会出现 NullPointerException

我假设您想将它设置为您链接的 MainActivity,因此您必须通过构造函数将其传递到 ClientThread,例如:

public class ClientThread implements Runnable {
     public ClientThread(MyCallback callback){
         this.callback = callback;
     }
}

然后更改:

cThread = new ClientThread();

cThread = new ClientThread(this);

但是如果你的回调函数想要做任何 UI 相关的事情,或者任何应该在主线程上 运行 的事情,你将不得不使用一个处理程序来 post 它到主线程。如果你想这样做,最简单的方法是将 Context 传递给 ClientThread 并执行如下操作:

public class ClientThread implements Runnable {
     /*your things*/
     Context mCtx;
     public ClientThread(Context context){
         this.mCtx = context;
         if(context instanceof MainActivity){
             this.callback = (MainActivity) callback;
         }
     }
}

然后将回调位更改为:

Handler mainHandler = new Handler(mCtx.getMainLooper());
mainHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.callbackCall();
            }
        });