2012-09-21 60 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