2012-09-21 64 views
2

我是Android新手。我有一個正在下載URL內容的AsyncTask。 我不希望AsyncTask直接操作用戶界面,並希望它將它作爲可重用的代碼,因此我將它放在它自己的文件中,並返回一個字符串。 問題是,返回發生在AsyncTask完成之前(即使我使用.excecute())的.get(),所以我沒有得到任何回報。 這裏是啥子我在此刻:Android AsyncTask無法直接訪問UI

package com.example.mypackage; 

import java.io.FileWriter; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.UnsupportedEncodingException; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.util.concurrent.ExecutionException; 

import android.os.AsyncTask; 

public class URLContent { 
private String content = "default value"; 

public String getContent(String URL){ 
    try { 
     new getAsyncContent().execute(URL).get(); 
    } catch (InterruptedException e) { 
     content = e.getMessage(); 
    } catch (ExecutionException e) { 
     content = e.getMessage(); 
    } 
    return content; 
} 

private class getAsyncContent extends AsyncTask<String, Integer, String> 
{ 
    @Override 
    protected void onPostExecute(String result) { 
     content = result; 
    } 

    @Override 
    protected String doInBackground(String... urls) { 
     try{ 
      return URLResponse(urls[0]); 
     } catch (Exception e){ 
      return e.getMessage(); 
     } 

    } 
} 

private String IStoString(InputStream stream) throws IOException, UnsupportedEncodingException { 
    try { 
     return new java.util.Scanner(stream, "UTF-8").useDelimiter("\\A").next(); 
    } catch (java.util.NoSuchElementException e) { 
     return ""; 
    } 
} 

private String URLResponse(String URLToget) throws IOException { 
    InputStream is = null; 

    try { 
     URL url = new URL(URLToget); 
     HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
     conn.setReadTimeout(10000 /* milliseconds */); 
     conn.setConnectTimeout(15000 /* milliseconds */); 
     conn.setRequestMethod("GET"); 
     conn.setDoInput(true); 
     conn.connect(); 
     is = conn.getInputStream(); 
     // Convert the InputStream into a string 
     String contentAsString = IStoString(is); 
     return contentAsString; 
    } finally { 
     if (is != null) { 
      is.close(); 
     } 
    } 
} 
} 

什麼是解決這個讓我的主線程莫名其妙地回來了結果的最佳方式是什麼? 我來過一些提及事件和回調的文章。這是最好的方式..?

+0

更新在它完成之前?可能是你的方法'URLResponse'返回'null',你認爲它不起作用。順便說一下,你的'AsyncTask'是通過你使用它的方式同步的。 –

+0

作爲一個附註,您應該遵循Java代碼約定。 Java類必須以大寫字母 – Bostone

回答

2

不要做get()。只需在doInBackground方法內有任何邏輯處理您的URL執行結果。你不需要返回任何東西。在您的特定情況下,問題是,get()方法是正確的走結果傳遞

這是異步執行,你不能用的AsyncTask是結果線性邏輯應用到它

+0

開頭,但是不應該在'get'中阻塞,直到結果被傳遞? –

+0

不,它只是產生線程,但在UI線程中立即執行get – Bostone

+0

我只在一個嘗試中使用get()來獲得結果。 在我的主線程中,我得到了「默認值」,但如果我將onPostExecute中的結果輸出到文件中,我將獲得URL內容。 我會傾向於避免onPostExecute中的邏輯,這是重點,以便我可以重新使用該代碼 – iasonas

1

更新UI前執行onPostExecute()的主要目的。爲了保持UI的實現和使用方式不同,您的Activity可以擴展您的getAsyncContent類並覆蓋onPostExecute()方法。此方法將在UI線程上執行。

1

如果您不需要異步任務的UI更新,只需創建一個簡單的線程來完成這些任務。完成後,只需發送廣播。

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     // Do the download here... 
     .... 
     // 
     sendBroadcast(some_intent); 
}).start(); 
2

感謝您的幫助。我會嘗試通過Alex擴展asyncTask類的解決方案,聽起來像一個乾淨的解決方案。

我設法通過在類中使用AsyncTask中的接口並在主類中添加事件偵聽器來完成我嘗試的操作。 所以我的課,現在得到的內容是這樣的:

package com.example.test; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.UnsupportedEncodingException; 
import java.net.HttpURLConnection; 
import java.net.URL; 

import android.os.AsyncTask; 

public class URLContent { 
public void getContent(String URL){ 
    new getAsyncContent().execute(URL); 
} 

public interface OnContentDownloadedListener{ 
    public abstract void onContentDownloaded(String content); 
} 
private OnContentDownloadedListener contentDownloadedListener = null; 
public void setOnContentDownloadedListener(OnContentDownloadedListener content){ 
    contentDownloadedListener = content; 
} 

private class getAsyncContent extends AsyncTask<String, Integer, String> 
{ 
    @Override 
    protected void onPostExecute(String result) { 
     contentDownloadedListener.onContentDownloaded(result); 
    } 

    @Override 
    protected String doInBackground(String... urls) { 
     try{ 
      return URLResponse(urls[0]); 
     } catch (Exception e){ 
      return e.getMessage(); 
     } 
    } 
} 

private String IStoString(InputStream stream) throws IOException, UnsupportedEncodingException { 
    try { 
     return new java.util.Scanner(stream, "UTF-8").useDelimiter("\\A").next(); 
    } catch (java.util.NoSuchElementException e) { 
     return ""; 
    } 
} 

private String URLResponse(String URLToget) throws IOException { 
    InputStream is = null; 

    try { 
     URL url = new URL(URLToget); 
     HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
     conn.setReadTimeout(10000 /* milliseconds */); 
     conn.setConnectTimeout(15000 /* milliseconds */); 
     conn.setRequestMethod("GET"); 
     conn.setDoInput(true); 
     conn.connect(); 
     is = conn.getInputStream(); 
     // Convert the InputStream into a string 
     String contentAsString = IStoString(is); 
     return contentAsString; 
    } finally { 
     if (is != null) { 
      is.close(); 
     } 
    } 
} 
} 

然後在我的主類我只是有一個事件偵聽器來處理你確定它返回的UI

urlContent.setOnContentDownloadedListener(new URLContent.OnContentDownloadedListener(){ 
      public void onContentDownloaded(String content){ 
//update UI or do something with the data 
} 
+0

爲什麼你接受自己的答案而不是Alex的?給他們的應有的 – Bostone

+0

抱歉,還沒有時間來測試Alex的答案呢。如果你知道它正在工作,我很樂意將它作爲答案。 – iasonas