2012-01-19 92 views
8
數據

我試圖將關於SO類似的問題,但沒有得到任何幫助。從安卓的AsyncTask返回

在我的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; 
      } 
     } 
    } 
+0

這將是更好,如果你使用BroadCasteReceiver http://developer.android.com/reference/android/content/BroadcastReceiver .html ..它可以讓你通過意圖傳遞數據。 – ngesh

回答

8

postExecute()不能返回一個值?調用AsyncTask的原始方法已失效,因爲您的AsyncTask正在後臺運行。當AsyncTask.execute()返回它仍然在後臺運行時,它是異步的,因此postExecute()不能返回值,因爲沒有任何值返回。

而不是你的AsyncTask需要一個參考回你的活動或其他一些對象,因此它可以發佈你的價值觀回去吧。在您的代碼中,調用execute()之後的行不能存在,因爲您的任務尚未完成。相反,你應該創建一個名爲updateSymbol(currentPrice,percentChange)方法,下面移動所有的代碼執行()在那裏,並在您的AsyncTask你應該傳遞給活動的參考。然後從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塊移動到方法的底部。

+0

Thnx這麼多。我是新來的android開發,並試圖理解這一點。你在AsyncTask中的意思是什麼,你應該通過一個對活動**的引用? – GAMA

+0

DownloadRecentQuote task = new DownloadRecentQuote(this)假設您正在從一個活動中執行此操作。如果您不在活動中執行DownloadRecentQuote,則可以將引用傳遞給正在創建DownloadRecentQuote實例的實例,然後找出某種方式從那裏更新UI。它看起來像你在一個活動中創建DownloadRecentQuote,因爲我看到一個帶有適配器的列表變量。 – chubbsondubs

3

從本質上講,AsyncTask.onPostExecute()是你做任何你想做的AsyncTask的doInBackground後做()被執行,執行結果得到返回。這應該被認爲是最佳做法。當從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提供了一種在編碼的時間返回的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線程上調用它,你可能會得到一個ANR異常。這是使用AsyncTask.get(),通過調用它的UI線程上的有效載荷,你實際上是使你的AsyncTask(工作線程)同步與UI線程中運行(通過使UI線程等待)。總之,這是可行的,但不推薦。

+0

我不認爲myAsyncTask.get()會長時間阻塞用戶界面,因爲它只是從'onPostExecute()'獲取計算數據。 –

+0

除了第14行「未來」的部分,你的回答是完美的。 –

1

只是爲了將來參考,因爲這個職位是一個小老頭:

我創建了具有在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; 
    } 
}