2013-08-22 46 views
2

好吧,我明白這個一般問題在這裏已經有很多次了,但我還沒有找到對我有意義的答案。幾乎我見過的每一個答案都只是說,「嘿,把這個放在你的方法中,你很好」,但是我沒有看到完整的例子,而且我嘗試過的方法也不起作用。我該如何使用RunOnUiThread更新屏幕上的一些TextViews

這是我收到的錯誤:

[mono] android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

所以,簡單地說,我有抓住從Web服務的一些信息,然後將Web服務結果投到幾個TextViews的活動。有人能幫我弄清楚我在哪裏以及如何使用RunOnUiThread()?下面的代碼:


using Android.App; 
using Android.OS; 
using System; 
using System.Web; 
using System.Net; 
using System.IO; 
using Newtonsoft.Json; 
using Android.Widget; 

namespace DispatchIntranet 
{ 
    [Activity (Label = "@string/Summary")]   
    public class SummaryActivity : Activity 
    { 
     private static readonly Log LOG = new Log(typeof(SummaryActivity)); 
     private TextView summaryTotalRegularLabel; 
     private TextView summaryTotalRollover; 
     private TextView summaryScheduledLabel; 
     private TextView summaryRemainingRegular; 
     private string url; 

     protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 

      // SET THE LAYOUT TO BE THE SUMMARY LAYOUT 
      SetContentView(Resource.Layout.Summary); 

      // INITIALIZE CLASS MEMBERS 
      init(); 

      if (LOG.isInfoEnabled()) 
      { 
       LOG.info("Making call to rest endpoint . . ."); 

       if (LOG.isDebugEnabled()) 
       { 
        LOG.debug("url: " + this.url); 
       } 
      } 

      try 
      { 
       // BUILD REQUEST FROM URL 
       HttpWebRequest httpReq = (HttpWebRequest)HttpWebRequest.Create(new Uri(this.url)); 

       // SET METHOD TO 'GET' 
       httpReq.Method = GetString(Resource.String.web_service_method_get); 

       // ASK FOR JSON RESPONSE 
       httpReq.Accept = GetString(Resource.String.web_service_method_accept); 

       // INVOKE ASYNCHRONOUS WEB SERVICE 
       httpReq.BeginGetResponse((ar) => { 
        HttpWebRequest request = (HttpWebRequest)ar.AsyncState; 

        using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse (ar)) 
        { 
         using (StreamReader reader = new StreamReader(response.GetResponseStream())) 
         { 
          // PUT RESPONSE INTO STRING 
          string content = reader.ReadToEnd(); 

          // CONVERT STRING TO DYNAMIC JSON OBJECT 
          var json = JsonConvert.DeserializeObject<dynamic>(content); 

          if (LOG.isDebugEnabled()) 
          { 
           LOG.debug("content: " + content); 
           LOG.debug("json: " + json); 

           LOG.debug("TOTAL_REGULAR_PTO_HOURS: " + json.d[0].TOTAL_REGULAR_PTO_HOURS); 
          } 

          // ** THIS IS WHAT WILL NOT WORK ** 
          this.summaryTotalRegularLabel.Text = json.d[0].TOTAL_REGULAR_PTO_HOURS; 
          this.summaryTotalRollover.Text = json.d[0].TOTAL_ROLLOVER_PTO_HOURS; 
          this.summaryScheduledLabel.Text = json.d[0].TOTAL_USED_PTO_HOURS; 
          this.summaryRemainingRegular.Text = json.d[0].TOTAL_REMAINING_PTO_HOURS; 
         } 
        } 
       }, httpReq); 
      } 
      catch (Exception e) 
      { 
       LOG.error("An exception occurred while attempting to call REST web service!", e); 
      } 
     } 

     private void init() 
     { 
      // GET GUID FROM PREVIOUS INTENT AND DETERMINE CURRENT YEAR 
      string guid = Intent.GetStringExtra("guid"); 
      int year = DateTime.Now.Year; 

      // BUILD URL 
      this.url = GetString(Resource.String.web_service_url) 
       + GetString(Resource.String.ws_get_pto_summary) 
       + "?" + "guid='" + HttpUtility.UrlEncode(guid) + "'" 
       + "&" + "year=" + HttpUtility.UrlEncode(year.ToString()); 

      // GET THE SUMMARY LABELS 
      this.summaryTotalRegularLabel = FindViewById<TextView>(Resource.Id.SummaryTotalRegular); 
      this.summaryTotalRollover = FindViewById<TextView>(Resource.Id.summaryTotalRollover); 
      this.summaryScheduledLabel = FindViewById<TextView>(Resource.Id.summaryScheduledLabel); 
      this.summaryRemainingRegular = FindViewById<TextView>(Resource.Id.SummaryRemainingRegular); 
     } 
    } 
} 
+0

@Grzegorz不,在Java中有一個RunOnUIThread,它允許你卸載一些在UI線程上運行的函數(它需要一個Runnable並且會在UI線程上調用它的Runnable)。通常,它是一種長時間運行線程的方式,不能通過AsyncTasks來執行UI後期處理或進度更新。 –

回答

3

當您進行Web服務調用,HttpWebRequest的創建一個新的線程上運行操作。這樣做是爲了防止用戶界面鎖定或跳過幀。一旦Web服務調用完成後,您需要返回UI線程來更新該線程上的UI組件。你可以通過幾種不同的方式來做到這一點。

首先,你可以用你的代碼在一個匿名函數調用就像這樣:

RunOnUiThread(()=>{ 
    this.summaryTotalRegularLabel.Text = json.d[0].TOTAL_REGULAR_PTO_HOURS; 
    this.summaryTotalRollover.Text = json.d[0].TOTAL_ROLLOVER_PTO_HOURS; 
    this.summaryScheduledLabel.Text = json.d[0].TOTAL_USED_PTO_HOURS; 
    this.summaryRemainingRegular.Text = json.d[0].TOTAL_REMAINING_PTO_HOURS; 
}); 

或者你也可以通過RunOnUiThread調用一個函數(jsonPayload是在類中的字段):

jsonPayload = json; 
RunOnUiThread(UpdateTextViews); 

... 


void UpdateTextViews() 
{ 
    this.summaryTotalRegularLabel.Text = jsonPayload.d[0].TOTAL_REGULAR_PTO_HOURS; 
    this.summaryTotalRollover.Text = jsonPayload.d[0].TOTAL_ROLLOVER_PTO_HOURS; 
    this.summaryScheduledLabel.Text = jsonPayload.d[0].TOTAL_USED_PTO_HOURS; 
    this.summaryRemainingRegular.Text = jsonPayload.d[0].TOTAL_REMAINING_PTO_HOURS; 

} 
+0

謝謝你,那個作品!我想,我沒有花時間去真正理解我在做什麼,我只是想讓它工作並繼續前進。感謝您解釋發生了什麼以及我需要做什麼,這非常有幫助。 – liltitus27

相關問題