如何在xml中设置 RecyclerView的 LayoutManager以及为什么不要这样做

原文:Android DTT #13 — How To Set RecyclerView’s LayoutManager in XML and Why You Shouldn’t

屏幕快照 2017-09-14 18.55.59.png 

绝大多数关于RecyclerView的教程在讲到如何设置LayoutManager的时候都是这样写的:

public void onCreate(Bundle savedInstanceState) {
    ....
    RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
    rv.setLayoutManager(new LinearLayoutManager(this));
    ....
}

实际上谷歌 “RecyclerView tutorial”这个关键词的前5个结果都是用的这种方式,包括来自 developers.android.com 的那篇也是。这就造成了Java代码是设置LayoutManager的唯一方式的印象。但实际上还有一个xml属性:app:layoutManager。下面是文档中关于这个属性的描述:

所要使用的布局管理器的类名称

这个类必须继承了android.support.v7.widget.RecyclerView$LayoutManager 并且有一个默认的或者带(android.content.Context, android.util.AttributeSet, int, int)签名的构造函数。

我们可以在xml中指定完全限定类名来使用LinearLayoutManager:

<android.support.v7.widget.RecyclerView
   android:id="@+id/rv"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   app:layoutManager="android.support.v7.widget.LinearLayoutManager"
    />

这跟前面的Java代码是等效的。一个垂直的reverseLayout为false的LinearLayoutManager。

如果想改变布局方向,可以使用 android:orientation="horizontal",同样还可以使用app:reverseLayout, app:stackFromEnd, app:spanCount等属性。

你也可以在xml中使用 GridLayoutManager 和 StaggeredGridLayoutManager。如果你使用一个自定义的LayoutManager,注意在自定义的类中提供所需的构造函数。

为什么Java代码的方式更受欢迎?

我以为这是support library的一个新功能,虽然现在用的人不多,但是今后会变得流行。但是并没有这样,原因是反射的问题。

我一直在思考它是如何工作的。因为属性一般只能提供很简单的值,比如integer, string等。但是为什么它可以提供一个对象?在稍微深入了下RecyclerView的源码之后我发现它使用了反射来实力化xml中给出的LayoutManager。你可以在这个类的createLayoutManager(Context, String, AttributeSet)函数中找到。

反射对于一个资源有限的系统来说是不好的。它非常慢,一般要尽量避免使用。

幸运的是我们知道了另一种设置LayoutManager的方法,但是也要记住尽量不要这样用。

ADTT (Android 开发提示与技巧) 是我打算在5月完成的31篇系列博客,这里是目录