简体   繁体   English

如何使用AsyncTask

[英]How to use AsyncTask

AsyncTask question AsyncTask问题

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 code. 这是我目前的代码,代码下面有一些问题。 MainActivity calls SomeClassWithHTTPNeeds, which then calls the JSONParser (AsyncTask<>) MainActivity调用SomeClassWithHTTPNeeds,然后调用JSONParser(AsyncTask <>)


MainActivity: 主要活动:

String station = SomeClassWithHTTPNeeds.getInstance().getStation(123);

SomeClassWithHTTPNeeds: SomeClassWithHTTPNeeds:

getStation {

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

JSONParser (AsyncTask< String, Void, String >) JSONParser(AsyncTask <String,Void,String>)

protected String doInBackground(); ==> Seperate thread
protected void onPostExecute(); ==> On GUI thread

I was thinking: --- Put the HTTPRequest in doInBackground(); 我在想:---把HTTPRequest放在doInBackground()中;

Problem is I'm not sure how to: get the JSONParser to return the JSONObject to the getStation method? 问题是我不知道如何:让JSONParser将JSONObject返回到getStation方法?

What I need to know 我需要知道的

=> Where should I return the JSONObject: in background or execute? =>我应该在哪里返回JSONObject:在后台还是执行?

=> How do I use the JSONParser once it's an AsyncTask? =>一旦它是AsyncTask,我如何使用JSONParser? Will the execute() function return the value? execute()函数会返回值吗?

=> AsyncTask< String, Void, String > ==> How does this work? => AsyncTask <String,Void,String> ==>这是如何工作的? It's the return type? 这是回归类型?

Thanks a lot! 非常感谢!

FAQs and general explaination of the usage of AsyncTask 常见问题和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(); 通常,您应该在单独的线程中执行网络操作- > doInBackground(); since you do not want your UI to freeze when a Network Operation takes its time. 因为您不希望在网络操作占用时间时冻结UI。 So you should connect to your Service or .php script or wherever you get the Data from inside the doInBackground() method. 因此,您应该连接到Service或.php脚本,或者从doInBackground()方法中获取数据的任何位置。 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. 然后,你还可以解析数据存在,并从返回的解析数据doInBackground()通过指定的返回类型的方法doInBackground()到你的欲望,更多关于那里。 The onPostExecute() method will then receive your returned values from doInBackground() and represent them using the UI. onPostExecute()则方法将从收到您返回的值doInBackground()和使用UI代表他们。

=> AsyncTask< String, Integer, Long> ==> How does this work? => AsyncTask <String,Integer,Long> ==>这是如何工作的?

In general, the AsyncTask class looks like this, which is nothing more than a generic class with 3 different generic types : 通常, AsyncTask类看起来像这样,它只不过是一个具有3种不同泛型类型的泛型类

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()). 您可以指定AsyncTask采用的参数类型,进度指示器类型和结果类型(doInBackGround()的返回类型)。

Here is an Example of an AsyncTask looking like this: 下面是一个AsyncTask的示例,如下所示:

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() ). 我们有参数的类型字符串,进度的类型整数和结果的类型长(返回类型为doInBackground() )。 You can use any type you want for Params, Progress and Result. 您可以使用Params,Progress和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? =>如何使用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). 在这种情况下,AsyncTask将String或String Array作为参数 ,一旦调用AsyncTask,它将如下所示:( 指定的参数用于AsyncTask的execute(param)方法)。

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() . 请注意,此调用没有返回值 ,您应该使用的唯一返回值是从doInBackground()返回的值。 Use the onPostExecute() method do make use of the returned value. 使用onPostExecute()方法确实可以使用返回的值。

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. 当AsyncTask正在执行时, .get()调用会导致UI线程被阻塞 (因此,如果操作花费的时间超过几毫秒,UI会冻结),因为执行不会在单独的线程中执行。 If you remove the call to .get() it will perform asynchronously. 如果删除对.get()的调用,它将异步执行。

=> What does this notation "execute(String... params)" mean? =>这个符号“执行(String ... params)”是什么意思?

This is a method with a so called " varargs " (variable arguments) parameter. 这是一个带有所谓“ varargs ”(变量参数)参数的方法。 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: 假设我们还在讨论AsyncTask ,可以在doInBackground(String... params)方法中以这种方式访问doInBackground(String... params)

 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 您可以在此处阅读有关AsyncTask的更多信息: http//developer.android.com/reference/android/os/AsyncTask.html

Also take a look at this AsyncTask example: https://stackoverflow.com/a/9671602/1590502 另请参阅此AsyncTask示例: https ://stackoverflow.com/a/9671602/1590502

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: 的AsyncTask:

public class callCarWeb extends 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 ## ##标题##

I think you can execute your HTTPRequest in your doInBackground of the Async task. 我认为您可以在Async任务的doInBackground中执行HTTPRequest And JSONParser at onPostExecute . JSONParseronPostExecute

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 . 现在,当您编写异步任务JSONParser时,此处的params类型为Stringprogress的类型为Voidresult的类型为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 . 通常人们会覆盖两个方法doInBackground()onPostExecute() ,第一个接受params并返回result ,第二个接受result These are protected methods you can't call em directly. 这些是您无法直接调用em的protected方法。 Then you might ask how to send param to doInBackground() , look at execute() API. 然后你可能会问如何将param发送到doInBackground() ,看看execute() API。

doInBackground() runs on background thread, its not a blocking call !! doInBackground()在后台线程上运行,它不是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, 而是在JSONParser或其他地方的interface上写,

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

now your JSONParser class will something like, 现在你的JSONParser类就像,

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的对象时,设置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. 现在你决定从哪里传递或创建自己的监听器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM