我有一个应用程序与几个屏幕。另外,我有一个全局运行的计时器,偶尔(每分钟左右)尝试从网站刷新它们的事务数据并将其存储在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