如何解决替换 AsyncTask 以连接套接字的问题?

Posted

技术标签:

【中文标题】如何解决替换 AsyncTask 以连接套接字的问题?【英文标题】:How to fix the Issue with replacing AsyncTask to connect socket? 【发布时间】:2022-01-11 12:50:11 【问题描述】:

我正在尝试使用This approach(Marked Answer) 将我的代码替换为AsyncTask 以在android 中的用户和服务器之间建立连接,这就是我所做的:

注意:我没有使用任何特定的模式,只是试图在基本结构上实现这一目标。

主要活动:

public class MainActivity extends AppCompatActivity 
    private ClientConnection connection;


    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        connection = new ClientConnection(inputServerIp.getText().toString(), inputUserName.getText().toString(), Integer.parseInt(inputPort.getText().toString()));
    

客户端连接:

public class ClientConnection 
    private Socket serverSocket;
    private ConnectionTask taskRunner;

    public ClientConnection(String ipAddress, String userName, int dstPort) 
        this.ipAddress = ipAddress;
        this.userName = userName;
        this.dstPort = dstPort;
    

    public void connect() 
        taskRunner.executeAsync(new ConnectionRunningTask(ipAddress, dstPort), (data) -> 
            serverSocket = data;
        );
    

连接任务:

public class ConnectionTask 

    private final Executor executor = Executors.newSingleThreadExecutor();
    private final Handler handler = new Handler(Looper.getMainLooper());

    public interface Callback<R> 
        void onComplete(R result);
    

    public void executeAsync(Callable<R> callable, Callback<R> callback) 
        executor.execute(() -> 
            try 
                final R result = callable.call();
                handler.post(() -> 
                    callback.onComplete(result);
                );
             catch (Exception e) 
                e.printStackTrace();
            
        );
    

ConnectionRunningTask:

public class ConnectionRunningTask implements Callable<Socket> 
    private final String ipAddress;
    private final Integer dstPort;

    public ConnectionRunningTask(String ipAddress, Integer dstPort) 
        this.ipAddress = ipAddress;
        this.dstPort = dstPort;
    

    @Override
    public Socket call() throws IOException 
        return new Socket(ipAddress, dstPort);
    

所以基于上面的代码,我将尝试解释我尝试过的内容以及当前的问题:

问题: 基于上面的代码,我在 connect() 中收到以下错误,它告诉我数据是 R,您不能将其设置为 serverSocket,因此错误我无法构建应用程序。

然后我尝试将 ConnectionTask 类(回调和可调用中的 R)中的所有 R 替换为 Socket,在这种情况下,应用程序能够构建和运行。

public interface Callback<Socket> 
    void onComplete(Socket result);


public void executeAsync(Callable<Socket> callable, Callback<Socket> callback) 
    executor.execute(() -> 
        try 
            final Socket result = callable.call();
            handler.post(() -> 
                callback.onComplete(result);
            );
         catch (Exception e) 
            e.printStackTrace();
        
    );

但是基于上述方法,当我点击连接按钮时会出现错误,这就是我所得到的:

2021-12-06 04:02:26.942 16417-16417/ir.atlaspio.atlasclientchat E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ir.atlaspio.atlasclientchat, PID: 16417
    java.lang.NullPointerException: Attempt to invoke virtual method 'void ir.atlaspio.atlasclientchat.networking.ConnectionTask.executeAsync(java.util.concurrent.Callable, ir.atlaspio.atlasclientchat.networking.ConnectionTask$Callback)' on a null object reference
        at ir.atlaspio.atlasclientchat.networking.ClientConnection.connect(ClientConnection.java:38)
        at ir.atlaspio.atlasclientchat.MainActivity$1.onClick(MainActivity.java:61)
        at android.view.View.performClick(View.java:4780)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
        at android.view.View$PerformClick.run(View.java:19866)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
2021-12-06 04:07:27.221 16417-16417/ir.atlaspio.atlasclientchat I/Process: Sending signal. PID: 16417 SIG: 9

在服务器端,我也检查了传入的连接,但那里什么也没发生...

【问题讨论】:

如何在ClientConnection 中实例化taskRunner @GuidoCardinali 你好,我已经更新了问题,很抱歉错过了实例化taskRunner 的那部分。 【参考方案1】:

您没有在ClientConnection 中实例化taskRunner。将此行添加到构造函数中:

public ClientConnection(String ipAddress, String userName, int dstPort) 
    this.ipAddress = ipAddress;
    this.userName = userName;
    this.dstPort = dstPort;
    this.taskRunner = new ConnectionTask(); // <-- this line here

【讨论】:

谢谢。我不知道我是怎么错过的……

以上是关于如何解决替换 AsyncTask 以连接套接字的问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 上建立套接字连接

示例:使用AsyncTask的Android双向网络套接字

第二个 AsyncTask 未执行

在 android studio 中使用 AsyncTask 从套接字读取数据

AsyncTask和套接字在android java中不起作用

如何使用 Runnable 回调替换 AsyncTask onProgressUpdate()