如何从AsyncTask获取字符串?

时间:2012-06-10 20:27:20

标签: android string android-asynctask

我有以下课程:

public class getURLData extends AsyncTask<String, Integer, String>{

@Override
protected String doInBackground(String... params) {
    String line;
    try {  
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(params[0]);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        line = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
    } catch (MalformedURLException e) {
        line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
    } catch (IOException e) {
        line = "<results status=\"error\"><msg>Can't connect to server</msg></results>";
    }
    return line;
}

@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
}

}

我试图这样称呼它:

String output = null;
output = new getURLData().execute("http://www.domain.com/call.php?locationSearched=" + locationSearched);

但输出变量没有获取数据,而是出现错误:

Type mismatch: cannot convert from AsyncTask<String,Integer,String> to String

8 个答案:

答案 0 :(得分:111)

方法execute会返回AynscTask本身,您需要致电get

output =
    new getURLData()
        .execute("http://www.example.com/call.php?locationSearched=" + locationSearched)
        .get();

这将启动一个新线程(通过execute),同时阻止当前线程(通过get),直到新线程的工作完成并返回结果。

如果您这样做,只需将异步任务转换为同步

但是,使用get的问题是因为它阻塞,所以需要在工作线程上调用它。但是,需要在主线程上调用AsyncTask.execute()。因此,尽管此代码可行,但您可能会得到一些不良结果。我还怀疑get()未经Google严格测试,他们可能会在某个地方引入错误。

参考:AsyncTask.get

答案 1 :(得分:18)

我宁愿创建回调而不是阻止UI线程。 在您的类创建方法,将在数据到达时调用。例如:

private void setData(String data){
    mTextView.setText(data);
}

然后在AsyncTask中实现onPostExecute:

@Override
protected void onPostExecute(String result) {
    setData(result);
}

然后在代码中的某处执行任务:

new getURLData().execute(...

当任务完成时,调用setData并填充mTextView。

AsyncTask.get()将填充您的UI,因此没有理由使用AsyncTask。

答案 2 :(得分:4)

如果用户点击该按钮,则必须等待内容,他们同时做什么?

为什么不这样做:

  1. 用户点击按钮。
  2. 检查连接性。如果用户未连接到Internet,请告诉他们。
  3. 通过发送Intent来发送HTTP请求来启动IntentService。
  4. 请求完成后,您发布通知。
  5. 用户单击通知,该通知将返回可执行下一步的活动。
  6. 这允许用户在处理请求时离开并执行任何操作。

    IntentService在后台运行自己的线程。当它收到一个Intent时,它会在onHandleIntent()上运行。当该方法完成时,服务被缓存:它不是活动的,但是当下一个Intent到达时它可以快速重新启动。

答案 3 :(得分:2)

  1. 在构造函数中获取上下文:

    public GetDataTask(Context context) {}

  2. 使用以下方法创建接口:

    void onDataRetrieved(String data);

  3. 在您创建Task对象的类中实现Interface(例如MainActivity

  4. 将Context强制转换为接口并调用onDataRetrieved Method

答案 4 :(得分:1)

这个ONE LINER为我工作:

String result = MyasyncTask.execute(type, usrPhoneA, usrPWDA).get();

答案 5 :(得分:0)

在下面的代码中,我从AsyncTask返回一个String(directorName)。

public class GetDirector {
    String id;
    private String baseURL = "http://www.omdbapi.com/?i=";
    private String finalURL = "";
    String theDirector;

    public GetDirector(String imdbID) throws ExecutionException, InterruptedException {
        id= imdbID;
        finalURL = baseURL + id + "&plot=full&r=json";
        System.out.println("GetDirector. finalURL= " + finalURL);
        theDirector = new GetDirectorInfo().execute().get();
    }

    public String getDirector (){
        return theDirector;
    }

    private class GetDirectorInfo extends AsyncTask<Void, Void,String> {
        @Override
        protected String doInBackground(Void... params) {
            String directorName = null;

            ServiceHandler sh = new ServiceHandler();

            // Making a request to url and getting response
            String jsonStr = sh.makeServiceCall(finalURL, ServiceHandler.GET);
            System.out.println("Act_DetailsPage. jsonStr= " + jsonStr);

            if (jsonStr != null) {
                try {
                    JSONObject everything = new JSONObject(jsonStr);

                    directorName = everything.getString(JSON_Tags.TAG_DIRECTOR);
                    System.out.println("directorName= "+ directorName);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println("Inside GetDirector. Couldn't get any data from the url");
            }
            return directorName;
        }
    }
}

答案 6 :(得分:0)

向task的构造函数添加一个context参数,该构造函数将引用存储结果数据的对象。

class PopulateArray extends AsyncTask<Integer, Integer, ArrayList<String>>
{
    Context _context; // context may be what ever activity or object you want to store result in
    PopulateArray(Context context)
    {
        _context = context;
    }
    @Override
    protected ArrayList<String> doInBackground(Integer... integers)
    {
        ArrayList<String> data = new ArrayList<String>();
        //manipulate
        return data;
    }

    @Override
    protected void onPostExecute(ArrayList<String> strings)
    {
        _context.setData(strings);
    }
}

答案 7 :(得分:0)

AsyncTask向UI发送数据的唯一方法是OttoEvent总线。注册一个方法,该方法将在用户界面中@Subscribe注释postmessage处理结果,并在onPostExecute的{​​{1}}方法中为其提供结果。< / p>