2013-05-18 116 views
8

在扩展AsyncTask的自定义类中存在一些问题。我的应用是针对Android 4.0.3,下面的代码适用于30多人测试它。然而,当我像下面那样调用新的AsyncRequest时,有两个用户正在看到应用程序崩溃。AsyncTask创建导致崩溃

我有一个工作日志记录到用户存储上的文本文件,并且不记录AsyncRequest构造函数中的条目。所以我必须假设崩溃发生在构造函数被调用之前。

遇到此崩溃的两个设备之一显然是运行Android 4.0.4。不知道其他设备正在运行什么。不幸的是我不能访问这两个设备,所以看不到logcat输出。

任何有关为什么对象创建导致崩溃的输入将不胜感激。

String url = "www.google.com"; 

new AsyncRequest(callback, context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); 

这里是全AsyncRequest类

public class AsyncRequest extends AsyncTask<String, String, String>{ 

HttpURLConnection connection; 
InputStream inStream; 
IApiCallback callback; 
Context context_; 

public AsyncRequest(IApiCallback callback, Context context) { 
    // Log entry added for testing. Never gets called. 
    FileLogger.getFileLogger(context).ReportInfo("Enter AsyncRequest Constructor"); 
    this.callback = callback; 
    context_ = context; 
} 

@Override 
protected String doInBackground(String... uri) { 

    try { 
     URL url = new URL(uri[0] + "?format=json"); 
     FileLogger.getFileLogger(context_).ReportInfo("Async Request: Sending HTTP GET to " + url); 

     connection = (HttpURLConnection) url.openConnection(); 
     connection.setConnectTimeout(5000); 
     connection.setReadTimeout(5000); 
     connection.addRequestProperty("Accept-Encoding", "gzip"); 
     connection.addRequestProperty("Cache-Control", "no-cache"); 

     connection.connect(); 

     String encoding = connection.getContentEncoding(); 

     // Determine if the stream is compressed and uncompress it if needed. 
     if (encoding != null && encoding.equalsIgnoreCase("gzip")) { 
      inStream = new GZIPInputStream(connection.getInputStream()); 

     } else { 
      inStream = connection.getInputStream(); 
     } 

     if (inStream != null) { 
      // process response 
      BufferedReader br = new BufferedReader(new InputStreamReader(inStream)); 
      StringBuilder sb = new StringBuilder(); 
      String line; 
      while ((line = br.readLine()) != null) { 
       sb.append(line); 
      } 

      return sb.toString(); 

     } 

    } catch (SocketTimeoutException e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: SocketTimeoutException", e); 
     Log.i("AsyncRequest", "Socket Timeout occured"); 
    } catch (MalformedURLException e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: MalformedUrlException", e); 
    } catch (IOException e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: IOException", e); 
     Log.i("doInBackground:","IOException"); 

     if (e != null && e.getMessage() != null) { 
      Log.i("doInBackground:",e.getMessage()); 
     } 
    } catch (Exception e) { 
     FileLogger.getFileLogger(context_).ReportException("Async Request: Exception", e); 

    } finally { 
     if (connection != null) 
      connection.disconnect(); 
    } 

    return null; 
} 

@Override 
protected void onPostExecute(String result) { 

    if (result != null) 
     FileLogger.getFileLogger(context_).ReportInfo("Async Request: Response is valid"); 
    else 
     FileLogger.getFileLogger(context_).ReportInfo("Async Request: Invalid response"); 

    callback.Execute(result); 
} 
} 

编辑:按照下面的评论。

这里是我称之为自定义AsyncTask的完整方法。日志中显示了创建AsyncTask的所有日志消息。没有例外。

该日志记录在创建我的AsyncRequest之前显示url值,并且URL根本没有格式错误。这正是我期待的。所有的

public void GetServerInfoAsync(IApiCallback callback, Context context) throws IllegalArgumentException, Exception { 

    if (callback == null) 
     throw new IllegalArgumentException("callback"); 

    if (context == null) 
     throw new IllegalArgumentException("context"); 

    try { 
     FileLogger.getFileLogger(context).ReportInfo("Build URL"); 
     String url = GetApiUrl("System/Info"); 
     FileLogger.getFileLogger(context).ReportInfo("Finished building URL"); 

     if (url != null) { 
      FileLogger.getFileLogger(context).ReportInfo("GetServerInfoAsync: url is " + url); 
      new AsyncRequest(callback, context).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); 
     } else { 
      FileLogger.getFileLogger(context).ReportError("GetServerInfoAsync: url is null"); 
     } 

    } catch (IllegalArgumentException iae) { 
     FileLogger.getFileLogger(context).ReportException("GetServerInfoAsync: IllegalArgumentException", iae); 
     throw iae; 
    } catch (Exception e) { 
     FileLogger.getFileLogger(context).ReportException("GetServerInfoAsync: Exception", e); 
     throw e; 
    } 
} 
+0

如果您已经发现错误发生在此请求之前,请在您调用之前显示该代码。 – Gustek

+0

您是否在创建'AsyncTask'的过程中将代码记录在代码中?也许这会让你看到哪条线实际上失败了? –

+1

Gustek。在我打电话之前似乎没有错误。我已将调用方法附加到我原来的帖子中。 – Redshirt

回答

0

首先,只是记住executeOnExecutor()不可用之前阿比11.你已经说,这个问题是一个4.0.4设备,而只是记住这一点。

下面是我将采取的步骤,以解决问题是什么。看起来好像你已经完成了所有那些ReportInfo()陈述中的一些。

首先,我假设您拨打GetServerInfoAsync的电话号码是try...catch,对吗?我正在检查是否因为您使用了Throw。此外,您已经添加日志记录以检查URL的错误。由于错误发生在您实际使用它之前,因此错误不能与url或任何Internet权限相关联。 您可以参考callbackcontext来调用AsyncTask代。您已经通过ReportInfo()添加了日志记录,这些日志参考了上下文,以及那些工作,是吗?因此,上下文不是你的问题。但是,你永远不会检查callback是什么。如果它为空,则会发出错误,但在您拨打AsyncRequest之前,您从未做过任何操作。试试ReportInfo(callback.toString())看看它是什么。

如果一切都失败了,它似乎是线程错误。为什么不尝试使用AsyncTask,而不是executeOnExecutor()。你真的需要超过1个后台线程吗?

+1

感谢您的回复。我的min/target sdk版本是15/17,我在没有ExecuteOnExecutor的情况下测试了相同的失败。调用方法确实被try/catch所包围。正如您所建议的那样,日志在GetServerInfoAsync方法内工作,直到AsyncTask实例被创建(或尝试)。下班后,我会尝试Wolframs的建议,并希望为每个人提供更具体的信息。 – Redshirt

0

抱歉没有及早回复。这里有很多问题。

首先......感谢Wolfram的建议,我能够发现异常并诊断问题是我的FileLogger(和另一个类)是静态引用,这两个平板电脑在运行时找不到引用。所以我最终从我的异步方法中删除了Logging。

其次,在做出上述修改之后,还有另一个问题,就是必须从主线程调用一个活套。原来,这两个平板电脑并没有从主线程中调用我的异步任务。所以我不得不使用MainLooper将异步调用放在一个新的Handler中。