Java 如何使用异步任务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18289623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:06:26  来源:igfitidea点击:

How to use AsyncTask

javaandroidmultithreadingandroid-asynctask

提问by Kevin Van Ryckegem

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 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? Will the execute() function return the value?

=> 一旦成为 AsyncTask,我该如何使用 JSONParser?execute() 函数会返回值吗?

=> AsyncTask< String, Void, String > ==> How does this work? It's the return type?

=> AsyncTask< String, Void, String > ==> 这是如何工作的?是返回类型?

Thanks a lot!

非常感谢!

采纳答案by Philipp Jahoda

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();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.

一般来说,你应该在一个单独的线程中进行网络操作-> doInBackground(); 因为您不希望您的 UI 在网络操作花费时间时冻结。因此,您应该连接到您的 Service 或 .php 脚本或从doInBackground()方法内部获取数据的任何地方。然后,您还可以解析那里的数据,并doInBackground()通过指定doInBackground()您想要的返回类型来从方法返回解析的数据,更多关于那里的内容。onPostExecute()然后该方法将接收您的返回值doInBackground()并使用 UI 表示它们。

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

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

In general, the AsyncTaskclass 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 AsyncTasktakes, 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 AsyncTasklooking 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()). You can use any type you want for Params, Progress and Result.

参数类型为字符串,进度类型为整数,结果类型为长(返回类型为doInBackground())。您可以为参数、进度和结果使用任何您想要的类型。

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?

=> 如何使用 AsyncTask?我怎样才能“调用”它?我怎样才能“执行”它?

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

在这种情况下,AsyncTask 将字符串或字符串数​​组作为参数,一旦 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(). Use the onPostExecute() methoddo make use of the returned value.

请注意,此调用没有返回值,您应该使用的唯一返回值是从 返回的值doInBackground()使用 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 nottake place in a separate thread. If you remove the call to .get() it will perform asynchronously.

.get() 调用会在AsyncTask 执行时导致 UI 线程被阻塞(因此,如果操作花费的时间超过几毫秒,UI 就会冻结),因为执行不会发生在单独的线程中。如果您删除对 .get() 的调用,它将异步执行。

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

=> 这个符号“execute(String... params)”是什么意思?

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:

这是一种带有所谓的“ varargs”(可变参数)参数的方法。为简单起见,我只想说这意味着您可以通过此参数传递给方法的实际值数量未指定,并且您传递给方法的任何数量的值都将被视为内部的数组方法。例如,此调用可能如下所示:

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)

 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

回答by Yajneshwar Mandal

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 {

公共类 callCarWeb 扩展了 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 ##

} ##标题##

回答by Ye Lin Aung

I think you can execute your HTTPRequestin your doInBackgroundof the Asynctask. And JSONParserat onPostExecute.

我想你可以执行你HTTPRequest在你doInBackground的的Async任务。而JSONParseronPostExecute

回答by Rupesh

do read some generics.

阅读一些泛型。

now, when you write your async task JSONParser here paramsis of type String, progressis of type Voidand resultis of type String. Read this.

现在,当您编写异步任务 JSONParser 时,这里params是 type Stringprogressis of typeVoidresulttype String。读这个

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

通常人们会覆盖两个方法doInBackground()onPostExecute(),第一个接受params并返回一个result,第二个接受那个result。这些是protected你不能直接调用 em 的方法。那你可能会问怎么发送paramdoInBackground(),看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 interfacein JSONParseror somewhere else like,

而是写interfaceJSONParser或其他地方,例如,

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

now your JSONParserclass 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 JSONParserset OnParseCompleteListener.

当您创建JSONParserset对象时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.

现在你决定从哪里传递或创建你自己的监听器。