2012-07-09 19 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