How to use AsyncTask

前端 未结 4 589
伪装坚强ぢ
伪装坚强ぢ 2020-12-03 22:55

AsyncTask question

I\'ve followed some tutorials but it still isn\'t clear to me. Here\'s the code I currently have with some questions below the co

相关标签:
4条回答
  • 2020-12-03 23:03
    package com.example.jsontest;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.zip.GZIPInputStream;
    import org.apache.http.Header;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.json.JSONObject;
    import android.util.Log;
    
    public class HttpClient {
        private static final String TAG = "HttpClient";
    
        public static JSONObject SendHttpPost(String URL, JSONObject jsonObjSend) {
    
            try {
                DefaultHttpClient httpclient = new DefaultHttpClient();
                HttpPost httpPostRequest = new HttpPost(URL);
    
                StringEntity se;
                se = new StringEntity(jsonObjSend.toString());
    
                httpPostRequest.setEntity(se);
                httpPostRequest.setHeader("Accept", "application/json");
                httpPostRequest.setHeader("Content-type", "application/json");
                httpPostRequest.setHeader("Accept-Encoding", "gzip"); 
    
                long t = System.currentTimeMillis();
                HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
                Log.i(TAG, "HTTPResponse received in [" + (System.currentTimeMillis()-t) + "ms]");
    
                HttpEntity entity = response.getEntity();
    
                if (entity != null) {
                    InputStream instream = entity.getContent();
                    Header contentEncoding = response.getFirstHeader("Content-Encoding");
                    if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
                        instream = new GZIPInputStream(instream);
                    }
    
                    String resultString= convertStreamToString(instream);
                    instream.close();
                    resultString = resultString.substring(0,resultString.length()-1); 
    
                    JSONObject jsonObjRecv = new JSONObject(resultString);
                    Log.i(TAG,"<JSONObject>\n"+jsonObjRecv.toString()+"\n</JSONObject>");
    
                    return jsonObjRecv;
                } 
    
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            return null;
        }
    
    
        private static String convertStreamToString(InputStream is) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
    
            String line = null;
            try {
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                    Log.e("JSON", ""+line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return sb.toString();
        }
    
    }
    

    Asynctask:

    public class callCarWeb extends AsyncTask {

        @Override
        protected void onPreExecute() {
            mDialog = new ProgressDialog(MainActivity.this);
            mDialog.setMessage("Please wait...");
            mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mDialog.setIndeterminate(true);
            mDialog.setCancelable(false);
            mDialog.show();
    
        }
    
        @Override
        protected Void doInBackground(Void... params) {
    
            try {
                JSONObject jsonObjSend = new JSONObject();
                jsonObjSend.put("username", username);
                jsonObjSend.put("password", passwd);
                Log.e("SEND", jsonObjSend.toString());
                JSONObject json = HttpClient.SendHttpPost("http://10.0.2.2/json/login.php", jsonObjSend);
                String status = json.getString("status");
                if(status.equalsIgnoreCase("pass")){
                    String id = json.getString("user_id");
                    Log.e("id", id);
                    String name = json.getString("name");
                    Log.e("name", name);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
    
    
    
            return null;
    

    }

        @Override
        protected void onPostExecute(Void result) {
            mDialog.cancel();
        }
    

    } ## Heading ##

    0 讨论(0)
  • 2020-12-03 23:06

    do read some generics.

    now, when you write your async task JSONParser here params is of type String, progress is of type Void and result is of type String. Read this.

    generally people overrides two methods doInBackground() and onPostExecute(), the first one takes params and returns a result and second one takes that result. These are protected methods you can't call em directly. Then you might ask how to send param to doInBackground(), look at execute() API.

    doInBackground() runs on background thread, its not a blocking call!!

    don't do this,

    JSONParser = new JSONParser();
    JSONObject station = parser.getJSONFromUrl("https://api....");
    return JSONObject.getString("station");
    

    instead write on interface in JSONParser or somewhere else like,

    public interface OnParseCompleteListener {
         void onParseComplete(JSONObject obj);
    }
    

    now your JSONParser class will something like,

    public class JSONParser extends AsyncTask<String, Void, String> {
         private OnParseCompleteListener mOnParseCompleteListener;
    
         public void setOnParseCompleteListener(OnParseCompleteListener listener) {
             mOnParseCompleteListener = listener;
         }
    
         protected String doInBackground(String... params) {
             /*
              * do http request and return a result
              */
         }
    
         protected void onPostExecute(String... result) {
             /*
              * parse the resulting json string or you can parse same string in 
              * doInBackground and can send JSONObject as a result directly.
              * at this stage say you have a JSONObject obj, follow 
              */
              if (mOnParseCompleteListener != null) {
                  mOnParseCompleteListener.onParseComplete(obj);
              }
         }
    }
    

    when you create an object of JSONParser set OnParseCompleteListener.

    JSONParser parser = new JSONParser();
    parser.setOnParseCompleteListener(listener);
    parse.execute("may be an url");
    

    now you decide from where to pass or create your own listener.

    0 讨论(0)
  • 2020-12-03 23:11

    I think you can execute your HTTPRequest in your doInBackground of the Async task. And JSONParser at onPostExecute.

    0 讨论(0)
  • 2020-12-03 23:18

    FAQs and general explaination of the usage of AsyncTask

    => Where should I do network operations? Where should I return my aquired values?

    In general, you should do Network Operations in a Seperate Thread -> doInBackground(); since you do not want your UI to freeze when a Network Operation takes its time. So you should connect to your Service or .php script or wherever you get the Data from inside the doInBackground() method. Then you could also parse the data there and return the parsed data from the doInBackground() method by specifying the return type of doInBackground() to your desires, more about that down there. The onPostExecute() method will then receive your returned values from doInBackground() and represent them using the UI.

    => AsyncTask< String, Integer, Long> ==> How does this work?

    In general, the AsyncTask class looks like this, which is nothing more than a generic class with 3 different generic types:

    AsyncTask<Params, Progress, Result>
    

    You can specify the type of Parameter the AsyncTask takes, the Type of the Progress indicator and the type of the result (the return type of doInBackGround()).

    Here is an Example of an AsyncTask looking like this:

    AsyncTask<String, Integer, Long>
    

    We have type String for the Parameters, Type Integer for the Progress and Type Long for the Result (return type of doInBackground()). You can use any type you want for Params, Progress and Result.

    private class DownloadFilesTask extends AsyncTask<String, Integer, Long> {
    
     // these Strings / or String are / is the parameters of the task, that can be handed over via the excecute(params) method of AsyncTask
     protected Long doInBackground(String... params) {
    
        String param1 = params[0];
        String param2 = params[1];
        // and so on...
        // do something with the parameters...
        // be careful, this can easily result in a ArrayIndexOutOfBounds exception
        // if you try to access more parameters than you handed over
    
        long someLong;
        int someInt;
    
        // do something here with params
        // the params could for example contain an url and you could download stuff using this url here
    
        // the Integer variable is used for progress
        publishProgress(someInt);
    
        // once the data is downloaded (for example JSON data)
        // parse the data and return it to the onPostExecute() method
        // in this example the return data is simply a long value
        // this could also be a list of your custom-objects, ...
        return someLong;
     }
    
     // this is called whenever you call puhlishProgress(Integer), for example when updating a progressbar when downloading stuff
     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }
    
     // the onPostexecute method receives the return type of doInBackGround()
     protected void onPostExecute(Long result) {
         // do something with the result, for example display the received Data in a ListView
         // in this case, "result" would contain the "someLong" variable returned by doInBackground();
     }
    }
    

    => How to use AsyncTask? How can I "call" it? How can I "execute" it?

    In this case, the AsyncTask takes a String or String Array as a Parameter which will look like this once the AsyncTask is called: (The specified parameter is used in the execute(param) method of AsyncTask).

    new DownloadFilesTask().execute("Somestring"); // some String as param
    

    Be aware, that this call does not have a return value, the only return value you should use is the one returned from doInBackground(). Use the onPostExecute() method do make use of the returned value.

    Also be careful with this line of code: (this execution will actually have a return value)

    long myLong = new DownloadFilesTask().execute("somestring").get();
    

    The .get() call causes the UI thread to be blocked (so the UI freezes if the operation takes longer than a few millisecons) while the AsyncTask is executing, because the execution does not take place in a separate thread. If you remove the call to .get() it will perform asynchronously.

    => What does this notation "execute(String... params)" mean?

    This is a method with a so called "varargs" (variable arguments) parameter. To keep it simple, I will just say that it means that the actual number of values you can pass on to the method via this parameter is not specified, and any amount of values you hand to the method will be treated as an array inside the method. So this call could for example look like this:

    execute("param1");
    

    but it could however also look like this:

    execute("param1", "param2");
    

    or even more parameters. Assuming we are still talking about AsyncTask, the parameters can be accessed in this way in the doInBackground(String... params) method:

     protected Long doInBackground(String... params) {
    
         String str1 = params[0];
         String str2 = params[1]; // be careful here, you can easily get an ArrayOutOfBoundsException
    
         // do other stuff
     }
    

    You can read more about AsyncTask here: http://developer.android.com/reference/android/os/AsyncTask.html

    Also take a look at this AsyncTask example: https://stackoverflow.com/a/9671602/1590502

    0 讨论(0)
提交回复
热议问题