2013-07-18 70 views
0

我的應用程序發送數據到服務器。它通常工作正常,直到用戶處於不良信號區域。如果用戶處於良好的信號區域,則以下代碼可正常工作併發送數據。AsyncTask.get()沒有進度條

String[] params = new String[]{compID, tagId, tagClientId, carerID, 
       formattedTagScanTime, formattedNowTime, statusForWbService, getDeviceName(), tagLatitude, tagLongitude}; 
     AsyncPostData apd = new AsyncPostData(); 

      apd.execute(params); 

private class AsyncPostData extends AsyncTask<String, Void, String> { 

     ProgressDialog progressDialog; 
     String dateTimeScanned; 

     @Override 
     protected void onPreExecute() 
     { 


      // progressDialog= ProgressDialog.show(NfcscannerActivity.this, 
       // "Connecting to Server"," Posting data...", true); 

      int buildVersionSdk = Build.VERSION.SDK_INT; 
      int buildVersionCodes = Build.VERSION_CODES.GINGERBREAD; 

      Log.e(TAG, "buildVersionSdk = " + buildVersionSdk 
        + "buildVersionCodes = " + buildVersionCodes); 

      int themeVersion; 
      if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD) { 

       themeVersion = 2; 

      }else{ 

       themeVersion = 1; 
      } 

      progressDialog = new ProgressDialog(NfcscannerActivity.this, themeVersion); 
      progressDialog.setTitle("Connecting to Server"); 
      progressDialog.setMessage(" Sending data to server..."); 
      progressDialog.setIndeterminate(true); 

      try{ 
      progressDialog.show(); 
      }catch(Exception e){ 

       //ignore 
      } 
     }; 


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

      Log.e(TAG, "carerid in doinbackground = " + params[3] + " dateTimeScanned in AsyncPost for the duplecate TX = " + params[4]); 

      dateTimeScanned = params[4]; 

      return nfcscannerapplication.loginWebservice.postData(params[0], params[1], params[2], params[3], params[4], 
        params[5], params[6], params[7] + getVersionName(), params[8], params[9]); 

     } 

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

       try{ 
       progressDialog.dismiss(); 
       }catch(Exception e){ 
        //ignore 
       } 

       if(result != null && result.trim().equalsIgnoreCase("OK") ){ 

        Log.e(TAG, "about to update DB with servertime"); 
        DateTime sentToServerAt = new DateTime(); 
        nfcscannerapplication.loginValidate.updateTransactionWithServerTime(sentToServerAt,null); 
        nfcscannerapplication.loginValidate.insertIntoDuplicateTransactions(dateTimeScanned); 

        tagId = null; 
        tagType = null; 
        tagClientId = null; 

        //called to refresh the unsent transactions textview 
        onResume(); 

       }else if(result != null && result.trim().equalsIgnoreCase("Error: TX duplicated")){ 
        Log.e(TAG, "response from server is Duplicate Transaction "); 


        //NB. the following time may not correspond exactly with the time on the server 
        //because this TX has already been processed but the 'OK' never reached the phone, 
        //so we are just going to update the phone's DB with the DupTX time so the phone doesn't keep 
        //sending it. 

        DateTime sentToServerTimeWhenDupTX = new DateTime(); 
        nfcscannerapplication.loginValidate.updateTransactionWithServerTime(sentToServerTimeWhenDupTX,null); 

        tagId = null; 
        tagType = null; 
        tagClientId = null; 



       }else{ 

        Toast.makeText(NfcscannerActivity.this, 
          "No phone signal or server problem", 
          Toast.LENGTH_LONG).show(); 
       } 
      } 

    }//end of AsyncPostData 

不良信號區域的應用程序往往會顯示幾分鐘的進度條,然後顯示一段時間的黑屏,導致應用程序無法使用。

我想過解決這個問題的方法是做以下事情。

String[] params = new String[]{compID, tagId, tagClientId, carerID, 
       formattedTagScanTime, formattedNowTime, statusForWbService, getDeviceName(), tagLatitude, tagLongitude}; 
     AsyncPostData apd = new AsyncPostData(); 
     try { 
      apd.execute(params).get(10, TimeUnit.SECONDS); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (TimeoutException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

這將導致的AsyncTask至10秒後取消,但因爲它正在執行有一個黑色的屏幕,直到數據被髮送,然後由進度幾的毫秒。

有沒有辦法在執行AsyncTask.get()時顯示進度條?

在此先感謝。馬特。

也有任何想法爲什麼當用戶處於不良信號區域並因此沒有來自服務器的響應時出現黑屏。這塞納里奧似乎導致應用程序很多的問題,其後行爲是不尋常的,像以後發送額外的交易。

[EDIT1]

public class SignalService extends Service{ 

    NfcScannerApplication nfcScannerApplication; 
    TelephonyManager SignalManager; 
    PhoneStateListener signalListener; 
    private static final int LISTEN_NONE = 0; 
    private static final String TAG = SignalService.class.getSimpleName(); 


    @Override 
    public void onCreate() { 
     super.onCreate(); 
     // TODO Auto-generated method stub 
     Log.e(TAG, "SignalService created"); 
     nfcScannerApplication = (NfcScannerApplication) getApplication(); 
     signalListener = new PhoneStateListener() { 
      public void onSignalStrengthChanged(int asu) { 
       //Log.e("onSignalStrengthChanged: " , "Signal strength = "+ asu); 
       nfcScannerApplication.setSignalStrength(asu); 

      } 
     }; 

    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     // TODO Auto-generated method stub 
     Log.e(TAG, "SignalService destroyed"); 
     SignalManager.listen(signalListener, LISTEN_NONE); 

    } 

    @Override 
    public void onStart(Intent intent, int startId) { 
     super.onStart(intent, startId); 
     // TODO Auto-generated method stub 
     Log.e(TAG, "SignalService in onStart"); 

     SignalManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
     SignalManager.listen(signalListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTH); 

    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     // TODO Auto-generated method stub 
     return null; 
    } 

} 
+0

使用'get()'只會使UX變差:[AsyncTask運行時出現黑屏](http://stackoverflow.com/a/15259698/2558882)。 – Vikram

+0

mmm是的我知道它阻止了UI線程,但我不知道如何設置一個定時器上的cancell而不使用.get()。 – turtleboy

+0

是否有可能使用處理程序取消asynctask? – turtleboy

回答

0

你並不需要一個計時器都做你嘗試什麼(由於某種原因,我還以爲你想根據您的意見環路AsyncTask上述這就造成了礦。)。如果我理解正確,那麼問題在於服務的喪失。您有一個開始的AsyncTask,根據特定條件可能會也可能不會完成。你的方法是在一定時間之後使用get和cancle這個任務,如果它在那之前沒有完成執行的話 - 假設這個任務沒有在10秒內完成,服務就失效了。

解決此問題的更好方法是使用布爾標誌來指示網絡連接是否可用,然後在服務丟失時停止執行任務。這裏是我從this post拿來的一個例子(我抱歉格式化我在一臺蹩腳的計算機上 - 所有東西 - IE8 - 所以我看不到代碼是什麼樣子)。

public class MyTask extends AsyncTask<Void, Void, Void> { 

private volatile boolean running = true; 
private final ProgressDialog progressDialog; 

public MyTask(Context ctx) { 
    progressDialog = gimmeOne(ctx); 

    progressDialog.setCancelable(true); 
    progressDialog.setOnCancelListener(new OnCancelListener() { 
     @Override 
     public void onCancel(DialogInterface dialog) { 
      // actually could set running = false; right here, but I'll 
      // stick to contract. 
      cancel(true); 
     } 
    }); 

} 

@Override 
protected void onPreExecute() { 
    progressDialog.show(); 
} 

@Override 
protected void onCancelled() { 
    running = false; 
} 

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

    while (running) { 
     // does the hard work 
    } 
    return null; 
} 

// ... 

} 

這個例子使用了一個進度對話框,允許用戶按下一個按鈕來取消任務。你不會那樣做,而是要檢查網絡連接性,並根據你的任務是否連接到互聯網來設置運行布爾值。如果連接丟失 - 運行將被設置爲false,這將跳過while循環並停止任務。

至於任務完成後的工作。你永遠不要使用get。 (1)將所有需要完成的事情放在onPostExecute的doInBackgroundCompletes之後(假設它不是太多),或者(2)如果需要使用接口將數據返回到開始活動。您可以添加一個接口,方法是將參數添加到您的任務構造函數中,或使用單獨的方法設置接口。例如

public void setInterface(OnTaskComplete listener){ 
    this.listener = listener; 
} 

凡OnTaskComplete監聽器被聲明爲您AsyncTask一個實例變量。請注意,我所描述的方法需要使用單獨的AsyncTask類。你的現在是私人的,這意味着你需要稍微改變你的項目。

UPDATE

檢查連接我會用這樣的事情。

public boolean isNetworkOnline() { 
boolean status=false; 
try{ 
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 
    NetworkInfo netInfo = cm.getNetworkInfo(0); 
    if (netInfo != null && netInfo.getState()==NetworkInfo.State.CONNECTED) { 
     status= true; 
    }else { 
     netInfo = cm.getNetworkInfo(1); 
     if(netInfo!=null && netInfo.getState()==NetworkInfo.State.CONNECTED) 
      status= true; 
    } 
}catch(Exception e){ 
    e.printStackTrace(); 
    return false; 
} 
return status; 

} 

您可以檢查是否有一個實際的網絡連接,您的應用程序可以通過它連接到它的服務器。這種方法不一定是公開的,可以是你的一部分AsyncTask類。就我個人而言,我在一個網絡管理員類中使用類似的東西來檢查各種網絡統計信息(其中一個是我可以連接到互聯網)。

在開始在doInBackground方法中執行循環之前,您需要檢查連接性,然後可以在該方法的整個過程中定期更新。如果netowkr可用,任務將繼續。如果沒有,它會停止。

調用AsyncTask內置的cancle方法是不夠的,因爲它只阻止onPostExecute運行。它實際上並沒有停止代碼的執行。

+0

嗨,感謝您的意見。我有點理解你的意思,但你可以詳細瞭解有關檢查網絡連接的細節。我編寫了檢查信號強度的代碼,但是我發現它有時不可靠(總是在沒有信號時說沒有信號)。我用信號碼發佈了一個編輯,是否正確?謝謝 – turtleboy