使用AsyncTask进行套接字

时间:2014-06-08 15:50:44

标签: android android-asynctask

我有这个Android代码:

private class myTask extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(String... params) {

       try {

             client = new Socket("192.168.1.2", 4444); 
             oos = new ObjectOutputStream(client.getOutputStream());
             ois = new ObjectInputStream(client.getInputStream());

             oos.writeUTF("LOGIN");
             oos.flush();

             String emailText = email.getText().toString();
             oos.writeUTF(emailText);
             oos.flush();

             String passwordText = password.getText().toString();
             oos.writeUTF(passwordText);
             oos.flush();

             string = ois.readUTF();

       }catch (ConnectException e){
           return "Host not found";
       }catch (IOException e) {
           return "Exception Caught";
       }
       return null;
    }

    @Override
    protected void onPostExecute(String result) {

        super.onPostExecute(result);   

        if ("Host not found".equalsIgnoreCase(result)){ 
            Toast.makeText(getApplicationContext(), "Host not found" ,Toast.LENGTH_LONG).show();
        }else if("Exception Caught".equalsIgnoreCase(result)){
            Toast.makeText(getApplicationContext(), "Connection error" ,Toast.LENGTH_LONG).show();
        }else{
             Toast.makeText(getApplicationContext(), "Connection established" ,Toast.LENGTH_LONG).show();
        }
        Toast.makeText(getApplicationContext(), string ,Toast.LENGTH_LONG).show();
        if(string.equals("Login successfully Done!")){
            startActivity(new Intent(Login.this, User.class));
        }

    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    register = (TextView)findViewById(R.id.register);
    login = (Button)findViewById(R.id.login);
    email = (EditText)findViewById(R.id.email);
    password = (EditText)findViewById(R.id.password);
    connection = (TextView)findViewById(R.id.connection);



    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment())
                .commit();
    }

    register.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View arg0) {
            startActivity(new Intent(Login.this, Register.class));
        }
    });

    login.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            new myTask().execute();

        }
    });
}

但每次点击登录按钮时我的连接都会创建。我希望我的应用程序在启动时连接到服务器,然后当我按下登录按钮时它会向服务器发送请求。如何更改我的代码?

感谢

2 个答案:

答案 0 :(得分:1)

我认为最简单的方法是远离AsyncTasks并转移到Threads。在onCreate函数中创建一个新线程,创建套接字并连接它,然后让它等待来自UI线程的通知(最简单的方法是等待信号量或消息队列)。然后让按钮的onClick通知套接字线程它需要登录。使用此设计,您将在启动时连接它,但在您请求之前不能登录。

您最担心的是,如果您的服务器因无活动而超时连接。但我认为您可以控制服务器以防止这种情况发生。

答案 1 :(得分:1)

这里的问题是您正在使用doInBackground()方法创建套接字。这意味着每次执行AsyncTask的实例时,将重新创建该套接字。您可能想要做的是子类Application或某种单例并在那里初始化您的套接字。然后让你的AsyncTask做类似的事情:

doInBackground(Object... params) {
    // do stuff
    Socket socket = Application.getSocket();
    // do stuff with the socket
}

这引入了一些复杂性,因为您需要在应用程序生命周期的适当位置处理正确打开/关闭套接字,但这是最清晰的解决方案。