10

异步任务问题

我已经遵循了一些教程,但我仍然不清楚。这是我目前在代码下方有一些问题的代码。MainActivity 调用 SomeClassWithHTTPNeeds,然后调用 JSONParser (AsyncTask<>)


主要活动:

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

SomeClassWithHTTP 需要:

getStation {

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

JSONParser (AsyncTask< String, Void, String >)

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

我在想: --- 将 HTTPRequest 放入 doInBackground();

问题是我不确定如何:让 JSONParser 将 JSONObject 返回到 getStation 方法?

我需要知道的

=> 我应该在哪里返回 JSONObject:在后台还是执行?

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

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

非常感谢!

4

4 回答 4

22

常见问题解答和 AsyncTask 用法的一般说明

=> 我应该在哪里进行网络操作?我应该在哪里返回我的获取值?

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

=> AsyncTask< String, Integer, Long> ==> 这是怎么工作的?

一般来说,这个AsyncTask类看起来是这样的,它只不过是一个具有 3 种不同泛型类型的泛型类:

AsyncTask<Params, Progress, Result>

您可以指定参数的AsyncTask类型、进度指示器的类型和结果的类型(doInBackGround() 的返回类型)。

这是一个AsyncTask看起来像这样的示例:

AsyncTask<String, Integer, Long>

我们有 String 类型的参数,Integer 类型的 Progress 和 Long 类型的 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();
 }
}

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

在这种情况下,AsyncTask 将一个字符串或字符串数​​组作为参数,一旦调用 AsyncTask,它将如下所示:(指定的参数用于 AsyncTask 的 execute(param) 方法)。

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

请注意,此调用没有返回值,您应该使用的唯一返回值是从返回的值doInBackground()使用 onPostExecute() 方法确实使用了返回值。

还要小心这行代码:(这个执行实际上会有一个返回值)

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

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

=> 这个符号“执行(字符串...参数)”是什么意思?

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

execute("param1");

但它也可能看起来像这样:

execute("param1", "param2");

甚至更多参数。假设我们还在讲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
 }

您可以在此处阅读有关 AsyncTask 的更多信息:http: //developer.android.com/reference/android/os/AsyncTask.html

另请查看此 AsyncTask 示例:https ://stackoverflow.com/a/9671602/1590502

于 2013-08-17T14:14:08.640 回答
0
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();
    }

}

异步任务:

公共类 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();
    }

} ## 标题 ##

于 2013-08-17T14:12:08.700 回答
0

我认为你可以执行你HTTPRequestdoInBackground任务AsyncJSONParseronPostExecute. _

于 2013-08-17T14:13:01.497 回答
0

读一些泛型。

现在,当你写你的异步任务 JSONParser 这里params是 type Stringprogressis of typeVoidresultis of type String。读这个

通常人们会覆盖两个方法doInBackground()onPostExecute()第一个接受params并返回一个result,第二个接受那个result。这些是protected您不能直接调用 em 的方法。然后你可能会问如何发送paramdoInBackground(),查看execute()API。

doInBackground()在后台线程上运行,它不是blocking call!!

不要这样做,

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

而是写interfaceJSONParser里面或其他地方,比如,

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

现在你的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);
          }
     }
}

当您创建JSONParserset的对象时OnParseCompleteListener

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

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

于 2013-08-17T14:40:51.770 回答