从AsyncTask Android返回数据

我试图提到类似的问题,但没有得到任何帮助。

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

以下是我所遵循的步骤:

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

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

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

问题出现在ASyncTask类中,因为postExecute方法不允许它的返回types是void以外的任何其他types。

我做错了什么?

任何帮助将是救命!

 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; } } } 

Solutions Collecting From Web of "从AsyncTask Android返回数据"

postExecute()不能返回一个值,因为谁或将返回到什么? 您调用AsyncTask的原始方法已经失效,因为您的AsyncTask正在后台运行。 这是AsyncTask.execute()返回它仍然在后台运行时的asynchronous含义,因此postExecute()不能返回一个值,因为没有什么可以返回它。

相反,您的AsyncTask需要引用回您的Activity或其他对象,以便将值发回给它。 在你的代码中,调用execute()之后的行不能在那里,因为你的任务还没有完成。 相反,您应该创build一个名为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 ); } } 

为所有活动创build一个基类真的很容易,所以你可以很容易的跟踪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 ); } } 

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

从本质上讲,在执行AsyncTask的doInBackground()并返回执行结果后,AsyncTask.onPostExecute()就是你要做的任何事情。 这应该被认为是最好的做法。

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

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

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

另外,Android API提供了一种在编码时返回一个AsyncTask执行结果的方法, AsyncTask.get() :

 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线程上调用它,您可能会得到一个ANRexception。 这是使用AsyncTask.get()的负载,通过在UI线程上调用它,实际上是使您的AsyncTask(工作线程)与UI线程(通过使UI线程等待)同步运行。 总之,这是可行的,但不build议。

只是为了以后的参考,因为这个post有点老了:

我创build了一个Activity类,它有一个onStart()方法和一个AsyncTask的独立类。 基于我的testing,在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; } }