为什么在线程中添加自定义视图时会跳过Measure pass?

时间:2016-03-14 11:48:57

标签: android xamarin xamarin.android measure

在Android中使用自定义视图时,我注意到以下在布局调用方面的差异。我在LinearLayout中有两个从FrameLayout派生的自定义视图。使用RunOnUiThread()方法在非UI线程中添加第一个FrameLayout。使用UIThread添加第二个FrameLayout。

现在差异我注意到使用UIThread直接添加的FrameLayout的度量命中是2.而使用RunOnUiThread()从非UIThread添加的FrameLayout的度量命中是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" />

1 个答案:

答案 0 :(得分:0)

这与RunOnUiThread无关。你欺骗了自己,因为这是一个时间问题。测量被调用两次,因为在android正确测量所有内容之前添加了视图。这意味着,android会多次调用测量值。

当你在点击按钮上添加你的视图或在UI线程上等一下(非阻塞)时,你可以重现这个。

[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 / mono-stdout(31936):UI测量达到1次