从AsyncTask Android返回数据

时间:2012-01-19 05:01:06

标签: android sqlite android-asynctask

我试图在SO上引用类似的问题,但没有得到任何帮助。

在我的Android应用程序中,我计划实现用户访问过的最近引用,即类似于最近访问过的网页。

以下是我正在遵循的步骤:

1。)每当用户打开任何公司视图时,从数据库中获取公司符号

2.)然后将当前符号与dateTime一起存储在数据库中。

3.。)对于从数据库中提取的所有符号,获取他们的current value%Change 并显示公司名称,当前值和%更改在列表中。

问题出现在ASyncTask类中,postExecute方法不允许其返回类型为void以外的其他类型。

我做错了吗?

任何帮助都可以节省生命!

String[] rsym,rcmp,rchg;
rdbM = new RecentDBManager(CompanyView.this);
try {
Calendar date1 = Calendar.getInstance();
SimpleDateFormat dateformatter = new SimpleDateFormat(
                            "dd/MM/yyyy HH:mm:ss");

String currentdate = dateformatter.format(date1.getTime());

rdbM.openDB();

//STEP 1
rsym = rdbM.getRecent_sym();

//STEP 2                
rdbM.setData(currentsymbol, currentdate);

rdbM.closeDB();

} catch (Exception e) {
throw new Error(" *** ERROR in DB Access *** "+ e.toString());
}

 //STEP 3
        for(int i=0;i<rsym.length;i++)
        {
            DownloadRecentQuote quotetask = new DownloadRecentQuote();
            recentquotetask
            .execute(new String[] { "http://abc.com/stockquote.aspx?id="
                        + rsym[i] });

 //CURRENT VALUE and %CHANGE which should be returned from ASyncTask class

            rcmp[i]=valuearr[0];
            rchg[i]=valuearr[1];
            }

            list1 = new ArrayList<HashMap<String, String>>();
            HashMap<String, String> addList1;

            for (int i = 0; i < limit; i++) 
            {
                addList1 = new HashMap<String, String>();
                addList1.put(RecentSym_COLUMN, rsym[i]);
                addList1.put(RecentCMP_COLUMN, rcmp[i]);
                addList1.put(RecentChg_COLUMN, rchg[i]);

                list1.add(addList1);

                RecentAdapter adapter1 = new RecentAdapter(
                    CompanyView.this, CompanyView.this, list1);
                listrecent.setAdapter(adapter1);
            }


private class DownloadRecentQuote extends AsyncTask<String, Void, String> {
    /* Fetching data for RecentQuote information */
    @Override
    protected String doInBackground(String... urls) {
        String response = "";
        for (String url : urls) {
            DefaultHttpClient client = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(url);
            try {
                HttpResponse execute = client.execute(httpGet);
                InputStream content = execute.getEntity().getContent();

                BufferedReader buffer = new BufferedReader(
                        new InputStreamReader(content));
                String s = "";
                while ((s = buffer.readLine()) != null) {
                    response += s;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return response;
    }

    @Override
    protected void onPostExecute(String result) {

        arr1 = result.split("@");

        if (arr1[0].length() != 0) {

            if (arr1[0].equals("1")) {

                arr = arr1[1].split(";");

            //RETURN 2 STRINGS
                            String valuearr[];
                valuearr[0] = arr[3];
                valuearr[1] = arr[6].concat("%");
                //return valuearr;
            }
        }
    }

3 个答案:

答案 0 :(得分:8)

postExecute()无法返回值,因为它返回的是谁或者什么?您调用AsyncTask的原始方法已经消失,因为您的AsyncTask正在后台运行。当AsyncTask.execute()返回它仍在后台运行时,它是异步的,因此postExecute()不能返回值,因为没有任何东西可以返回它。

相反,您的AsyncTask需要一个引用回您的Activity或其他一些对象,以便它可以将您的值发回给它。在您的代码中,调用execute()之后的行不能存在,因为您的任务尚未完成。相反,您应该创建一个名为updateSymbol(currentPrice,percentChange)的方法,在那里移动execute()下面的所有代码,并在AsyncTask中传递对Activity的引用。然后从onPostExecute()方法调用updateSymbol(currentPrice,percentChange)。

但是,如果你有一个对一个Activity的引用,你可以在doInBackground()运行时将其销毁,并且当postExecute()运行时,它应该只删除结果或不尝试更新UI。例如,用户旋转他们的电话导致活动被销毁。我发现最好在活动中保存对AsyncTask的引用,这样如果活动被销毁,它可以取消()它。您可以调用AsyncTask.cancel()然后检查您的任务是否被取消,如:

public void postExecute( String result ) {
    if( !isCanceled() ) {
       // do your updating here
       activity.setSymbol( result );
    }
}

为所有活动创建基类非常容易,因此您可以轻松跟踪正在运行的AsyncTasks:

public class BaseActivity extends Activity {

   List<AsyncTask> runningTasks;

   public void onStop() {
       for( AsyncTask task : runningTasks ) {
          task.cancel(true);
       }
   }

   public AsyncTask start( AsyncTask task ) {
      runningTasks.add( task );
      return task;
   }

   public void done( AsyncTask task ) {
      runningTasks.remove( task );
   }
}

一些快速指示。你不需要执行(new String [] {“blah”+ blah})。 Java中的Varargs允许您这样做。执行(“blah”+ blah)。你也正在捕捉异常并继续而不是真正处理它们。当一些事情发生真正发生因为你的应用程序捕获它们时会很难,并且就像没有发生任何事情一样继续。如果出现错误,您可能希望向用户提供一些反馈并停止尝试执行该过程。停止,向用户显示错误,让他们做下一件事。将catch块移动到方法的底部。

答案 1 :(得分:3)

本质上,在执行AsyncTask的doInBackground()并返回执行结果之后,AsyncTask.onPostExecute()是您要执行的任何操作。这应被视为最佳做法。

当从UI线程调用AsyncTask()。execute()时(注意必须从UI线程调用此方法),Android框架创建一个工作线程并开始运行您在AsyncTask.doInBackground()中编写的任何内容在这个工作线程上。此时(在调用新的AsyncTask()。execute()之后),UI线程继续在新的AsyncTask()。execute()之后执行代码。所以现在在运行时,你有两个线程(UI和工作线程)同时运行。

但AsyncTask执行结果何时何地从工作线程返回到UI线程?

工作线程(doInBackground())完成并返回到UI线程的点是AysncTask.onPostExecute()。一旦AsyncTask完成,该方法就保证由UI线程上的框架调用。换句话说,我们不关心在运行时何时以及何时调用AsyncTask.onPostExecute(),我们只需要保证它将在最后的某个阶段被调用。这就是为什么这个方法不返回执行结果的原因 - 相反,它要求执行结果作为doInBackground()中唯一的方法参数传入。

此外,Android API提供了一种在编码时{@ 3}}返回AsyncTask执行结果的方法:

MyAsyncTask myAsyncTask = new MyAsyncTask();

// This must be called from the UI thread:
myAsyncTask.execute();

// Calling this will block UI thread execution:
ExecutionResult result = myAsyncTask.get();

请记住,AsyncTask.get()将阻止调用线程的执行,如果你在UI线程上调用它,你可能会得到一个ANR异常。这是使用AsyncTask的有效负载.get(),通过在UI线程上调用它,实际上是使AsyncTask(工作线程)与UI线程同步运行(通过使UI线程等待)。总而言之,这是可行的,但不推荐。

答案 2 :(得分:1)

仅供将来参考,因为这篇文章有点旧:

我创建了一个Activity类,它有一个onStart()方法和一个单独的AsyncTask类。根据我的测试,在doInbackground()方法之后,结果将首先发送到活动,然后运行onPostExecute()。这是因为基于logcat,我首先得到了我的第一个响应数据(由服务器发送),然后这个响应将再次显示在活动中,并且onPostExecute()中的最后一个消息将显示。

活动代码:

@Override
    protected void onStart() {
        super.onStart();
        String str = "***";
        if(isConnectedToInternet()){
            myAsyncTask.execute();

            try {
                if(myAsyncTask.get())
                    str = myAsyncTask.getResponseMsg();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (CancellationException e) {
                e.printStackTrace();
            }
        }
        Log.i("Data returned by server2:", str);
    }

AsyncTask代码:

public class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {

    private URL url;
    private HttpURLConnection conn;
    private String strResponseMsg;

    public MyAsyncTask(String url) throws MalformedURLException{
        this.url = new URL(url);
    }


    @Override
    protected void onPreExecute() {
        Log.i("Inside AsyncTask", "myAsyncTask is abut to start...");
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        boolean status = false;

        try {
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(Manager.ConnTimeout);
            conn.setReadTimeout(Manager.ReadTimeout);

            int responseCode = conn.getResponseCode();
            Log.i("Connection oppened", "Response code is:" + responseCode);
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                if (in != null) {
                    StringBuilder strBuilder = new StringBuilder();
                    // Read character by character              
                    int ch = 0;
                    while ((ch = in.read()) != -1)
                        strBuilder.append((char) ch);

                    // Showing returned message
                    strResponseMsg = strBuilder.toString(); 
                    Log.i("Data returned by server:", strResponseMsg);

                    status = true;
                }
                in.close();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }       

        return status;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        Log.i("Inside AsyncTask", "myAsyncTask finished its task. Returning data to caller...");
    }

    public String getResponseMsg(){
        return strResponseMsg;
    }
}