2015-08-27 60 views
0

在if語句內登錄時,我可以成功獲取「startTime」變量的值。當我嘗試從if語句之外訪問此變量時,就會出現我的問題。變量作用域[JAVA]

public class MainActivity extends AppCompatActivity { 
String startTime = ""; 
String endTime = ""; 
.... 
.... 
.... 
public void dailyHours(){ 
    //Retrieve clockInId (ObjectID for clockInTime) 
    ParseQuery<ParseObject> startQuery = ParseQuery.getQuery("clockIn"); 
    startQuery.getInBackground(clockInId, new GetCallback<ParseObject>() { 
     public void done(ParseObject clockIn, ParseException e) { 
      if (e == null) { 
       startTime = clockIn.getString("Time"); 
       Log.d(TAG, "StartTime: " + startTime); 
      } else { 
       // something went wrong 
      } 
     } 
    }); 

    //Retrieve clockOutId (ObjectID for clockOutTime) 
    ParseQuery<ParseObject> endQuery = ParseQuery.getQuery("clockOut"); 
    endQuery.getInBackground(clockOutId, new GetCallback<ParseObject>() { 
     public void done(ParseObject clockOut, ParseException e) { 
      if (e == null) { 
       endTime = clockOut.getString("Time"); 
       Log.d(TAG, "EndTime: " + endTime); 
      } else { 
       // something went wrong 
      } 
     } 
    }); 

}

例如,當Log.d()被移動到ParseQuery以外,開始時間返回空。

public void dailyHours(){ 
    //Retrieve clockInId (ObjectID for clockInTime) 
    ParseQuery<ParseObject> startQuery = ParseQuery.getQuery("clockIn"); 
    startQuery.getInBackground(clockInId, new GetCallback<ParseObject>() { 
     public void done(ParseObject clockIn, ParseException e) { 
      if (e == null) { 
       startTime = clockIn.getString("Time"); 
      } else { 
       // something went wrong 
      } 
     } 
    }); 
    Log.d(TAG, "StartTime: " + startTime); //startTime returns an empty string when moved here. 

回答

2

GetCallback<ParseObject>()方法異步調用(在另一個線程),所以實際上分配startTime = clockIn.getString("Time")可以Log.d(TAG, "StartTime: " + startTime)之後執行。

你在這裏有「競爭條件」。

+0

本質上,我試圖做的是從解析中檢索兩個對象,然後取兩者的差異。你能指導我正確的方向,以解決我的問題?我怎樣才能確保'startTime'和'endTime'首先被啓動?這樣我就可以回去並改變它。 – jchav

+0

可能的修正之一是添加:'Object timeLock = new Object();'到MainActivity,然後檢查'synchronized(timeLock){if(startTime.length()> 0 && endTime.length()> 0)//計算差異}'每個內部'if(e == null)'block –

2

無論如何要麼if要麼else被執行。並且您每次都在if部分設置值。如果您的代碼在else區塊中,則表示if沒有執行,這意味着未設置值。 如果要訪問ifelse中的值,請在if區塊之前設置該值。

2

變量的範圍沒有問題,這是一個同步問題。在這裏你有一個競爭條件。這是因爲如果getInBackground。它們不會在同一個線程中執行。

而在startQuery.getInBackground之後,它激發了exectuion的新線程。並直接來到下一行。

Log.d(TAG, "StartTime: " + startTime); //startTime returns an empty s 

並且在那裏不能保證背景已經完成並且在進入上述行之前執行回調方法。

+0

如何保證在其餘執行前完成背景? – jchav

+0

其實你不應該。這是與同步的關鍵。您啓動後臺線程的原因不是阻止應用程序主線程的執行。如果你阻止它,你會得到ANR錯誤,並且應用程序崩潰。這就是爲什麼在執行後臺任務後,我們有回調方法來處理/執行主線程上的任何內容。 –