How to create asyncTask to prevent networkOnMainTh

2019-07-05 01:48发布

问题:

I'm new to android application development. I tried to develop an android server client chat

for my first project. This is the code for the client side. When the client press btnJoin,

it will connect to the server and send a string. I've read many example and many of them

looks like this. I got a networkOnMainThreadException. How do I make an asyncTask to prevent

this problem? Any help would be much appreciated.

btnJoin = (Button) findViewById(R.id.buttonJoin);
btnJoin.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Socket socket = null;
        DataOutputStream dataOutputStream = null;
        DataInputStream dataInputStream = null;
        try {
            socket = new Socket("192.168.1.4", 9092);
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());
            dataOutputStream.writeUTF("Hello server!");
            txtIP.append(dataInputStream.readUTF() + "\n");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dataOutputStream != null) {
                try {
                    dataOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
});

回答1:

Change your code as:

   btnJoin.setOnClickListener(new OnClickListener() {
    @Override
   public void onClick(View view){

              new LongOperation().execute("");

    }
}

private class LongOperation extends AsyncTask<String, Void, String> {
     Socket socket = null;
     String strresult="";
        DataOutputStream dataOutputStream = null;
        DataInputStream dataInputStream = null;
          @Override
          protected String doInBackground(String... params) {

        try {
            socket = new Socket("192.168.1.4", 9092);
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());
            dataOutputStream.writeUTF("Hello server!");
            strresult.append(dataInputStream.readUTF() + "\n");
         //   txtIP.append(dataInputStream.readUTF() + "\n");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dataOutputStream != null) {
                try {
                    dataOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (dataInputStream != null) {
                try {
                    dataInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

                return strresult;
          }      

          @Override
          protected void onPostExecute(String result) {
                TextView txtIP= (TextView) findViewById(R.id.txtIP);
              //  txtIP.append(result + "\n");
                txtIP.setText(result + "\n");

          }

          @Override
          protected void onPreExecute() {
          }

    }  


回答2:

Use AsyncTask like this :

First have it nested in your class, it should look similar to :

private class Communicator extends AsyncTask<Void, Void, Boolean> {
    String tmp;
    String err;

    @Override
    protected Boolean doInBackground() {

        try {
                socket = new Socket("192.168.1.4", 9092);
                dataOutputStream = new DataOutputStream(socket.getOutputStream());
                dataInputStream = new DataInputStream(socket.getInputStream());
                dataOutputStream.writeUTF("Hello server!");


         } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (dataOutputStream != null) {
                    try {
                        dataOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (dataInputStream != null) {
                    try {
                        dataInputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

        return true;
    }

    @Override
    protected void onPreExecute() {

    }

    @Override
    protected void onPostExecute(Boolean result) {
         txtIP.append(dataInputStream.readUTF() + "\n");            


    }
}

When you have AsyncTask,you can start it like this :

...
@Override
public void onClick(View v) {
Communicator c=new Communicator();
c.execute();
}
....


回答3:

try to implement this code in your app

private class LongOperation extends AsyncTask<Object, Integer, Object> {

        @Override
        protected void onPreExecute() {



            super.onPreExecute();
        }

        @Override
        protected Object doInBackground(Object... params) {
            //do hard work here
                                return params;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {


        }

        @Override
        protected void onPostExecute(Object result) {



            super.onPostExecute(result);
        }
    } 


回答4:

AsyncTask must be subclassed to be used. The subclass will override at least one method (doInBackground(Params...)), and most often will override a second one (onPostExecute(Result).)

Here is an example of subclassing:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

Once created, a task is executed very simply:

 new DownloadFilesTask().execute(url1, url2, url3);

for more details refer below links...

http://www.vogella.com/articles/AndroidPerformance/article.html

http://developer.android.com/reference/android/os/AsyncTask.html