由缓慢的度量/布局传递

时间:2018-05-12 09:50:05

标签: android performance android-fragments animation

我的应用程序有一个项目列表,点击其中一个会带来一个片段,其中包含该项目的详细信息。细节包含一些有点复杂的RecyclerView(许多带FlexBoxLayoutManager的小视图),测量/布局传递可以超过50ms。

该延迟导致应用程序在片段转换开始时丢弃几帧,导致相当明显的跳#34;

我看到了一些可能的方法来避免这种情况:

  1. 不要填充RecyclerView(或使其成为存根),直到转换完成。缺点:用户看到一个半空片段动画。
  2. 延迟整个转换,直到测量并布置新片段。缺点:用户反馈延迟。
  3. 启动列表的退出动画,但延迟输入动画,直到测量并布置新片段。这就是我想做的事。
  4. 不幸的是,退出动画必须在主线程上运行,测量/布局也是如此;测量/布局没有AsyncLayoutInflater,对吗?

    那么,那么,真的没有办法实现#3吗?如果是这样,有没有人有更好的解决方案?

    演示应用

    这个应用程序只需在onMeasure()方法中添加一个睡眠,只要"慢速测量"选中复选框。

    此处&#39; sa screen recording - 请注意复选框切换时的区别,跳转方式(左侧最明显的文字和旧/新片段之间的右边缘)。< / p>

    MainActivity.kt

    var beSlow = false
    
    class SlowWidget @JvmOverloads constructor(
            context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    ) : TextView(context, attrs, defStyleAttr) {
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            if (beSlow) {
                SystemClock.sleep(100)
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        }
    }
    
    class SlowFragment : Fragment() {
        override fun onCreateView(inflater: LayoutInflater, parent: ViewGroup?, state: Bundle?): View {
            return inflater.inflate(R.layout.fragment, parent, false)
        }
    }
    
    class MainActivity : AppCompatActivity() {
        var i = 0
        val colors = arrayOf(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.CYAN)
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.main)
        }
    
        fun viewClicked(v: View): Unit {
            beSlow = slowbox.isChecked
            supportFragmentManager.beginTransaction()
                    .setCustomAnimations(R.anim.slide_in, R.anim.slide_out)
                    .replace(R.id.container, SlowFragment().apply {
                        arguments = Bundle().apply {
                            putInt("color", colors[i++ % colors.size])
                        }
                    })
                    .commit()
        }
    }
    

    RES /布局/ main.xml中

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:text="Switch"
            android:onClick="viewClicked"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <CheckBox
            android:id="@+id/slowbox"
            android:text="slow measure"
            android:checked="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
    

    RES /布局/ fragment.xml之

    <?xml version="1.0" encoding="utf-8"?>
    <se.dolkow.debug.animdemo.SlowWidget
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:text="Hello World!"
        android:textColor="#000"
        android:gravity="center_vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/rainbow"
        />
    

    RES /抽拉/ rainbow.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle"
        >
        <gradient
            android:startColor="#ffff0000"
            android:centerColor="#ff00ff00"
            android:endColor="#ff8000ff"
            />
    </shape>
    

    RES /动画/ slide_in.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:shareInterpolator="false"
        >
        <translate android:fromXDelta="100%p" android:toXDelta="0"
            android:interpolator="@android:anim/linear_interpolator" />
    </set>
    

    RES /动画/ slide_out.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:shareInterpolator="false">
        <translate android:fromXDelta="0" android:toXDelta="-100%p"
            android:interpolator="@android:anim/linear_interpolator" />
    </set>
    

0 个答案:

没有答案