2013-05-18 11 views
8

Có một số vấn đề với lớp tùy chỉnh mở rộng AsyncTask. Ứng dụng của tôi đang nhắm mục tiêu Android 4.0.3 và mã bên dưới hoạt động tốt cho hơn 30 người thử nghiệm nó. Tuy nhiên có hai người dùng đang gặp sự cố ứng dụng khi tôi gọi AsyncRequest mới như dưới đây.Tạo AsyncTask gây ra sự cố

Tôi có một trình ghi nhật ký đang hoạt động đang ghi vào tệp văn bản trên bộ nhớ người dùng và không ghi lại mục nhập trong hàm tạo AsyncRequest. Vì vậy, tôi phải giả định rằng sự cố xảy ra trước khi hàm tạo được gọi.

Một trong hai thiết bị gặp sự cố này đang chạy Android 4.0.4. Không chắc chắn thiết bị khác đang chạy. Thật không may tôi không 'có quyền truy cập vào hai thiết bị để không thể nhìn thấy một đầu ra logcat.

Bất kỳ đầu vào nào về lý do tạo đối tượng gây ra sự cố sẽ được đánh giá cao.

String url = "www.google.com"; 

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

Và đây là lớp AsyncRequest đầy đủ

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); 
} 
} 

EDIT: Theo ý kiến ​​dưới đây.

Đây là phương pháp đầy đủ mà tôi gọi là AsyncTask tùy chỉnh của mình. Tất cả các thông điệp ghi nhật ký mà tôi có để tạo AsyncTask được hiển thị trong nhật ký. Không có ngoại lệ nào.

Ghi nhật ký hiển thị giá trị url ngay trước khi tạo AsyncRequest của tôi và URL không bị định dạng sai. Đó là những gì tôi đang mong đợi.

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

Nếu bạn đã phát hiện ra lỗi là trước yêu cầu này, hãy hiển thị mã trước khi bạn gọi nó. – Gustek

+0

Bạn đã đăng nhập vào mã trong quá trình chạy để tạo 'AsyncTask' chưa? Có lẽ điều này sẽ cho phép bạn xem dòng nào thực sự thất bại? –

+1

Gustek. Lỗi không xuất hiện trước khi tôi gọi nó. Tôi đã thêm phương thức gọi vào bài đăng gốc của mình. – Redshirt

Trả lời

0

Trước hết, chỉ cần ghi nhớ rằng executeOnExecutor() không có sẵn trước khi Api 11. Bạn đã nói vấn đề là với một thiết bị 4.0.4, nhưng chỉ cần ghi nhớ điều này.

Dưới đây là các bước tôi sẽ thực hiện để khắc phục sự cố là vấn đề gì. Dường như bạn đã thực hiện một vài trong số này với tất cả các câu lệnh ReportInfo() đó.

Trước tiên, tôi giả định cuộc gọi của bạn là GetServerInfoAsync nằm trong phạm vi try...catch, đúng không? Tôi đang kiểm tra vì bạn sử dụng số Throw. Ngoài ra, bạn đã thêm nhật ký để kiểm tra lỗi với url. Vì các lỗi xảy ra trước khi bạn thực sự sử dụng nó, lỗi không thể có với url hoặc bất kỳ quyền truy cập internet nào. Bạn gọi thế hệ AsyncTask với các tham chiếu đến callbackcontext. Bạn đã thêm ghi nhật ký qua ReportInfo() tham chiếu ngữ cảnh và những công việc đó, vâng? Do đó, ngữ cảnh không phải là vấn đề của bạn. Tuy nhiên, bạn không bao giờ kiểm tra xem callback là gì. Bạn ném một lỗi nếu nó là null, nhưng bạn không bao giờ làm bất cứ điều gì với nó trước khi bạn gọi AsyncRequest. Hãy thử một số ReportInfo(callback.toString()) để xem nó là gì.

Nếu mọi thứ khác không thành công, có vẻ như đó là lỗi với luồng. Tại sao không thử sử dụng AsyncTask, thay vì executeOnExecutor(). Bạn có thực sự cần nhiều hơn 1 chủ đề nền không?

+1

Cảm ơn bạn đã trả lời. Min/phiên bản sdk mục tiêu của tôi là 15/17, tôi đã thử nghiệm mà không có 'ExecuteOnExecutor' với cùng một lỗi. Phương pháp gọi thực sự được bao quanh bởi một try/catch. Như bạn đã đề xuất, việc ghi nhật ký không hoạt động trong phương thức GetServerInfoAsync, cho đến khi cá thể AsyncTask được tạo (hoặc đã cố gắng). Sau giờ làm việc, tôi sẽ thử đề xuất của Wolframs và hy vọng có thêm thông tin cụ thể cho mọi người. – Redshirt

0

Xin lỗi vì không quay lại sớm hơn. Có rất nhiều vấn đề ở đây. Trước hết ... Nhờ đề xuất của Wolfram, tôi có thể bắt được ngoại lệ và chẩn đoán rằng vấn đề là FileLogger của tôi (và một lớp khác) là tham chiếu tĩnh và hai máy tính bảng này không thể tìm thấy tham chiếu trong thời gian chạy . Vì vậy, tôi đã kết thúc việc xóa Đăng xuất khỏi các phương thức không đồng bộ của mình.

Thứ hai, sau khi thực hiện các thay đổi ở trên, có một vấn đề khác là một looper phải được gọi từ chuỗi chính. Hóa ra là hai máy tính bảng này không gọi công việc không đồng bộ của tôi từ chủ đề chính. Vì vậy, tôi đã phải bao gồm các cuộc gọi async trong một Handler mới bằng cách sử dụng MainLooper.