2013-08-22 6 views
2

좋아요, 그래서이 일반적인 질문은 여기에 여러 번 묻지 만, 아직 나에게 맞는 답을 찾지 못했습니다. 내가 본 모든 거의 모든 대답은 단지 "당신의 방법에 이것을 던져라. 당신은 훌륭합니다."라고 말하면서, 그러나 나는 완전한 예제를 보지 못하고있다. 그리고 내가 시도한 것은 작동하지 않는다.RunOnUiThread를 사용하여 화면의 일부 TextViews를 업데이트하는 방법

은 여기에 나타나는 오류입니다 :

그래서, 간단하게 말해서
[mono] android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

, 내가 웹 서비스에서 몇 가지 정보를 잡고 다음 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

:

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는 클래스의 필드이다) @ Grzegorz 아니요, Java에서 RunOnUIThread를 사용하면 UI 스레드에서 실행되는 일부 함수를 오프로드 할 수 있습니다 (Runnable을 사용하고 UI 스레드에서 Runnable을 호출합니다). 일반적으로 UI 후 처리 또는 진행 업데이트를 수행하기 위해 AsyncTasks가 될 수없는 장기 실행 스레드의 방식입니다. –

답변

3

당신이 웹 서비스 호출은 HttpWebRequest를이에서 작업을 실행하기 위해 새로운 스레드를 생성 할 때. 이는 사용자 인터페이스가 프레임을 잠 그거나 건너 뛰지 않도록하기 위해 수행됩니다. 웹 서비스 호출이 완료되면 해당 스레드에있는 UI 구성 요소를 업데이트하려면 UI 스레드로 돌아 가야합니다. 당신은 몇 가지 다른 방법으로 그렇게 할 수 있습니다.

첫째, 당신과 같이 익명 함수 호출에서 코드를 포장 할 수 있습니다

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

관련 문제