2013-07-18 40 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