由于Android.os.NetworkOnMainThreadException而设计AsyncTask类的问题

时间:2014-07-16 09:46:06

标签: android android-asynctask

尝试改进我的应用程序的源代码我注意到在许多活动中我有不同的AsyncTasks正在做同样的事情:从互联网上下载文档或图像。所以我决定将所有类中的所有类抽象出来,这样我就可以完成所有这些。

/*
 * Class for downloading documents or images from internet
 */
public class taskDownloader extends AsyncTask<Void,Void,Void>{

  // Type of download
  static final int DOC = 1;
  static final int IMAGE = 2;

  public String urlFetch;         // Url from download content
  public int operation;           // 'DOC' or 'IMAGE'
  public taskInterface listener;  // Notify events
  public InputStream file;        // Result of downloading a DOC
  public Bitmap image;            // Result of downloading an IMAGE

  /*
   * Set listener to events
   */
  public void setListener(taskInterface listener){
    this.listener = listener;
  }

  /*
   * Download a document by url for example an XML file
   */
  public void downloadDoc(String url){
    this.urlFetch = url;
    this.operation = DOC;
    this.execute();
  }

  /*
   * Download an image by url
   */
  public void downloadImage(String url){
    this.urlFetch = url;
    this.operation = IMAGE;
    this.execute();
  }

  @Override
  protected Void doInBackground(Void... params) {

    // Ask about operation requested
    switch(operation){

        case DOC:
            try{
                URL url = new URL(urlFetch);
                URLConnection urlCon = url.openConnection();
                file= urlCon.getInputStream();  // Saving the file

            }catch(Exception e){}
            break;

        case IMAGE:

            // Not yet coded
            break;
    }

    return null;
 }

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);

    Log.d("APP", "Downloaded!");

    // Test reading the inputstream and where I get exeception
    try{
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        String line;
        br = new BufferedReader(new InputStreamReader(this.file));
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        Log.d("APP", sb.toString());
    }catch(Exception e){
        Log.d("APP", "Error" + e);
    }

    this.listener.onFinished();
}

public InputStream getInputStream(){
    return this.file;
}
}

好吧,此外,我已经创建了一个简单的界面,用于从AsynTask到执行任务的通知。并且我不会在活动中使用此AsyncTask独占,例如在从Internet下载XML并存储在内部存储中的类中,我不必在UI上进行更改。

public interface taskInterface {

    public abstract void onFinished();

}

我的问题是我无法访问下载结果(属性&#34;文件&#34;通过getInputStream()方法)因为我得到了Android.os.NetworkOnMainThreadException。对于测试,在onPostExecute()方法中,我写了几行来读取InputStream,这里得到了问题。但是在doInBackground()上放置相同的代码效果很好。怎么可能? 异常来源来自UI线程上的执行互联网代码,但这行没有与此相关的代码。它只是BufferedReader,没有连接到任何地方。我的连接我已正确放在doInBackground但是onPostExecute我只阅读下载的结果我没有连接网站。 :(

    // Test reading the inputstream
    try{
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        String line;
        br = new BufferedReader(new InputStreamReader(this.file));
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        Log.d("APP", sb.toString());
    }catch(Exception e){
        Log.d("APP", "Error" + e);
    }

什么是BufferedReader连接到URL?我不明白是否只读取在doInBackground方法上下载的结果......

LogCatg

 07-16 12:08:05.945: W/ActivityThread(5042): Application com.example.lectorrss is waiting for the debugger on port 8100...
 07-16 12:08:05.955: I/System.out(5042): Sending WAIT chunk
 07-16 12:08:05.985: I/dalvikvm(5042): Debugger is active
 07-16 12:08:06.165: I/System.out(5042): Debugger has connected
 07-16 12:08:06.165: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:06.375: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:06.585: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:06.795: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:07.005: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:07.215: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:07.425: I/System.out(5042): waiting for debugger to settle...
 07-16 12:08:07.635: I/System.out(5042): debugger has settled (1400)
 07-16 12:08:07.745: D/SPLASH_SCREEN_ACTIVITY(5042): Descargando información portales
 07-16 12:08:07.745: D/SPLASH_SCREEN_ACTIVITY(5042): Descargado
 07-16 12:08:07.865: I/PGA(5042): New SOCKET connection: ample.lectorrss (pid 5042, tid 5058)
 07-16 12:08:07.875: I/PGA(5042): New SOCKET connection: ample.lectorrss (pid 5042, tid 5042)
 07-16 12:08:07.965: D/dalvikvm(5042): GC_FOR_ALLOC freed 76K, 24% free 7469K/9795K, paused 10ms
 07-16 12:08:08.005: I/dalvikvm-heap(5042): Grow heap (frag case) to 12.370MB for 3072012-byte allocation
 07-16 12:08:08.015: D/dalvikvm(5042): GC_FOR_ALLOC freed 1K, 19% free 10467K/12803K, paused 10ms
 07-16 12:08:08.045: D/dalvikvm(5042): GC_CONCURRENT freed 0K, 19% free 10468K/12803K, paused 0ms+0ms
 07-16 12:08:08.235: D/APP(5042): Descargado
 07-16 12:08:08.255: D/Error(5042): Errorandroid.os.NetworkOnMainThreadException

编辑:我真正的问题是,如果BufferedReader没有连接任何地方,它会抛出异常。只读取doInBackground()

上预先填充的变量

1 个答案:

答案 0 :(得分:1)

您看到的问题是,虽然您通过调用urlCon.getInputStream()获得了对该流的引用,但您尚未从该流读取。然后,将此引用传递给UI线程,然后从中读取,这会导致网络操作获取数据,并且您收到所描述的异常。

如果您将要从流中读取的调用移动到后台线程中,它将解决您的问题。