我有一個應用程序與幾個屏幕。另外,我有一個全局運行的計時器,偶爾(每分鐘左右)嘗試從網站刷新它們的事務數據並將其存儲在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
}
}
預先感謝您。 :)
Java通過基本上關注synchronized關鍵字的互斥來實現這一點。您可以使用一個塊(如建議的Faizan),或者您可以使用一種方法,例如public synchronized void threadSafeMethod(); – Joel 2012-07-09 16:53:06
真棒答案,謝謝你的++知識。然而,這引發了一個新問題 - 如果發生碰撞,應用程序現在會掛起,直到解決問題。由於我正在檢索網頁,因此可能需要等待幾秒鐘才能完成。有沒有辦法在獲取之前緩存jTransactions的值,以便ShowTransactions函數在發生衝突時可以使用緩存的值? – 2012-07-09 17:33:04
編輯上述:如果我按照你的建議換行同步,我仍然會遇到同樣的問題(空值)。如果我在同步中包含GetPage()行,除了掛起外,它工作正常。 – 2012-07-09 17:39:44