2012-07-09 80 views
0

我有一個應用程序與幾個屏幕。另外,我有一個全局運行的計時器,偶爾(每分鐘左右)嘗試從網站刷新它們的事務數據並將其存儲在JSONArray(static JSONArray jTransactions)中。Android JAVA:讀取線程正在訪問的變量

當您進入交易屏幕時,它所做的第一件事是用jTransactions的內容填充一個ListView,並且它會每隔幾秒刷新顯示的信息。但是,如果Web線程當前正在運行,則我會爲所有內容獲取空值。

我已經掌握了足夠的編碼知識來了解它是一個線程問題,但是我對JAVA/Android開發知道如何處理它還不夠豐富。而我的Google-fu可能會很弱,但我發現的唯一答案不適用或涉及大量重寫。

我想我的問題是這樣的 - 我怎麼改變我的代碼,以便我的活動和獲取線程之間沒有直接的衝突?

另外我完全接受我的代碼可能很醜陋;正如我所說,我仍然在學習這個平臺。

以下是我正在運行的線程的削減的版本:

 static int iRefreshTransactions = 30000; 
     static boolean bRefreshingTransactions = false; 
     static Calendar cLastRefreshTransactions = null; 
     final Runnable mRefreshTransactions = new Runnable() { 
      public void run() { 
       mHandler.removeCallbacks(this); 
       Thread T = new tRefreshTransactions(); 
       T.start(); 
      } 
     }; 
     private class tRefreshTransactions extends Thread { 
      @Override 
      public void run() { 
      bRefreshingTransactions = true; 
      RetrieveTransactions(); 
       bRefreshingTransactions = false; 
       handler.sendEmptyMessage(0); 
      } 
      private Handler handler = new Handler() { 
       @Override 
       public void handleMessage(Message msg) { 
        cLastRefreshTransactions = Calendar.getInstance(); 
        ShowToast("cLastRefreshTransactions(): " + cLastRefreshTransactions.getTime().toLocaleString()); 
        mHandler.postDelayed(mRefreshTransactions, iRefreshTransactions); 
      } 
      }; 
      private Handler failhandler = new Handler() { 
       @Override 
       public void handleMessage(Message msg) { 
        // handle the failure somehow 
       } 
      }; 
     } 

這裏的RetrieveTransactions的削減的版本()代碼:

// Retrieve the user's latest transactions from the website. 
    public boolean RetrieveTransactions() { 
     String result; 
     FailureReason = ""; 
     iTransactions = 0; 

     // Retrieve the Page. 
     result = GetPage(Url); 

     // Strip the transactions from the page and convert them to a JSONArray. 
     try { 
      String sTransactions = textExtract(result, "var dataTable1Data=", ";\n", 0); 
      jTransactions = new JSONArray(sTransactions); 
      iTransactions = jTransactions.length(); 
      return true; 
     } catch (JSONException e1) { 
      // Generally if it fails during this, there was no JSONArray to parse (hence no transactions). 
      FailureReason = "No Transactions Found"; 
      return false; 
     } 
    } 

最後這裏的縮減在列表視圖中顯示交易的下線代碼,其在活動啓動時以及其後每隔5秒左右被稱爲:

public void ShowTransactions() { 
    try { 
     if (!bRefreshingTransactions) { 
      if (iTransactions==0) { 
       return; 
      } 
      if (iTransactions==0) return; 
      List<String> listContents = new ArrayList<String>(iTransactions); 
      for (int i = 0; i < iTransactions; i++) { 
       listContents.add(jTransactions.getString(iTransactions - i - 1)); 
      } 
      lvRecentTransactions.setAdapter(new ArrayAdapterTransactions(MyContext, listContents)); 
     } 
    } catch (Exception e) { 
     // Do error stuff here 
    } 
} 

預先感謝您。 :)

回答

2

這似乎是互斥問題。使jTransaction同步或將jTransaction變量放入synchonized塊中。

synchronized(jTransactions){ 
     String sTransactions = textExtract(result, "var dataTable1Data=", ";\n", 0); 
     jTransactions = new JSONArray(sTransactions); 
     iTransactions = jTransactions.length(); 
    } 

我沒有測試代碼,但我希望同步將幫助你。

+0

Java通過基本上關注synchronized關鍵字的互斥來實現這一點。您可以使用一個塊(如建議的Faizan),或者您可以使用一種方法,例如public synchronized void threadSafeMethod(); – Joel 2012-07-09 16:53:06

+0

真棒答案,謝謝你的++知識。然而,這引發了一個新問題 - 如果發生碰撞,應用程序現在會掛起,直到解決問題。由於我正在檢索網頁,因此可能需要等待幾秒鐘才能完成。有沒有辦法在獲取之前緩存jTransactions的值,以便ShowTransactions函數在發生衝突時可以使用緩存的值? – 2012-07-09 17:33:04

+0

編輯上述:如果我按照你的建議換行同步,我仍然會遇到同樣的問題(空值)。如果我在同步中包含GetPage()行,除了掛起外,它工作正常。 – 2012-07-09 17:39:44