2016-03-14 2 views
0

Я заметил разницу в раскладках разговора при работе с пользовательскими представлениями в Android. У меня есть два пользовательских представления, полученных из FrameLayout внутри LinearLayout. Первый FrameLayout добавляется в поток без UI, используя метод RunOnUiThread(). Второй FrameLayout добавляется с помощью UIThread.Зачем пропускать пропуск при добавлении пользовательского представления в поток?

Теперь разница, которую я замечаю, заключается в том, что метка обращения к FrameLayout, которая добавляется напрямую с использованием UIThread, равна 2. В то время как мера попадает для FrameLayout, которая добавляется из не-UIThread с использованием RunOnUiThread(), равна 1. Обычно в Android, метка показов для пользовательского представления равна 2. Но Почему пропускается второй шаг при добавлении представления с помощью параметра RunOnUiThread()?

Кто-нибудь знает причину этого различия в макете проходит при использовании потоков в Xamarin.Android? Я приложил мой MainActivity код для справки:

MainActivity.cs

public class MainActivity : Activity 
{ 
    int count = 1; 

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

     // Set our view from the "main" layout resource 
     SetContentView(Resource.Layout.Main); 

     var view = FindViewById<LinearLayout>(Resource.Id.Linear); 
     Task.Factory.StartNew(() => 
     { 
      System.Threading.Thread.Sleep(500); 
      RunOnUiThread(() => 
      { 
       var threadView = new CustomViewInsideThread(this); 
       view.AddView(threadView); 
      }); 
     }); 

     var nonThreadView = new CustomViewOusideThread(this); 
     view.AddView(nonThreadView); 
    } 
} 

public class CustomViewInsideThread : FrameLayout 
{ 
    public CustomViewInsideThread(Context context) 
     : base(context) 
    { 

    } 
    int hitCount = 0; 
    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     base.OnMeasure(widthMeasureSpec, heightMeasureSpec); 
     hitCount++; 
     Console.WriteLine("Measure hit " + hitCount.ToString() + "time"); 
    } 
} 

public class CustomViewOusideThread : FrameLayout 
{ 
    public CustomViewOusideThread(Context context) 
     : base(context) 
    { 

    } 
    int hitCount = 0; 
    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    { 
     base.OnMeasure(widthMeasureSpec, heightMeasureSpec); 
     hitCount++; 
     Console.WriteLine("Measure hit " + hitCount.ToString() + "time"); 
    } 
} 

Main.axml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:id="@+id/Linear" 
    android:layout_height="fill_parent" /> 
+0

Может быть, не имеет отношения к вашему вопросу , но заметили ли вы, что вы вызываете 'SetContentView (Resource.Layout.Main);' дважды !? И: не могли бы вы добавить свой Main.axml? –

+0

Hi @ Sven-MichaelStübe, Извините, это по ошибке, я добавил, что он дважды не имеет последствий для этой проблемы. Я добавил код Main.axml. – Harikrishnan

ответ

0

Это не имеет ничего общего с RunOnUiThread , Вы обманули себя, потому что это вопрос времени . Измерение вызывается дважды, потому что представление добавляется до того, как android все правильно измерил. Это означает, что андроид будет вызывать измерение несколько раз.

Вы можете воспроизвести это при добавлении вашего вида на кнопку щелчка или немного подождать в потоке пользовательского интерфейса (без блокировки).

[Activity(Label = "App3", MainLauncher = true, Icon = "@drawable/icon")] 
public class MainActivity : Activity 
{ 
    int count = 1; 

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

     SetContentView(Resource.Layout.Main); 
     var btn = FindViewById<Button>(Resource.Id.btn); 

     // add view on button click 
     btn.Click += (sender, args) => 
     { 
      var view = FindViewById<LinearLayout>(Resource.Id.Linear); 
      var nonThreadView = new CustomViewOusideThread(this); 
      view.AddView(nonThreadView); 
     }; 
    } 

    protected async override void OnStart() 
    { 
     base.OnStart(); 

     var view = FindViewById<LinearLayout>(Resource.Id.Linear); 


     Task.Factory.StartNew(() => 
     { 
      System.Threading.Thread.Sleep(1500); 
      RunOnUiThread(() => 
      { 
       var threadView = new CustomViewInsideThread(this); 
       view.AddView(threadView); 
      }); 
     }); 

     await Task.Delay(1000); // non blocking wait on UI thread 
     var nonThreadView = new CustomViewOusideThread(this); 
     view.AddView(nonThreadView); 

    } 
} 

И даст вам:

03-14 16: 33: 15,990 I/моно-стандартный вывод (31936): UI Мера хит 1time

+0

Привет @ Sven-Michael Stube, Спасибо за объяснение. Означает ли это, что удаление или уменьшение количества времени сна в моем коде должно устранить проблему? – Harikrishnan

+0

Привет @ Свен-Майкл Штубе, Я не совсем понимаю эту точку зрения. «Измерение вызывается дважды, потому что представление добавлено до того, как Android все правильно измерил». Можете ли вы, пожалуйста, направить меня, где я могу найти информацию об этих вызовах измерения и о его работе для лучшего понимания? – Harikrishnan

+0

Возможно, это решает проблему **, но ** ее вопрос о времени/состоянии гонки. Поэтому вы не можете быть уверены, что будет первым, если вы используете «RunOnUiThread». Планировщик решает, когда он выполняет ваше действие. Почему количество вызовов «OnMeasure» критично для вас? Как правило, результат не должен зависеть от количества вызовов, только по спецификациям контента и измерения. –

Смежные вопросы