Android日历视图减慢布局速度

17

这让我感到疯狂。我在我的Android应用程序中有一个使用RelativeLayout布局的片段。问题是,由于某种原因,它需要很长时间来呈现,仅加载大约4个元素就要花费约5秒钟的时间。

其中一个元素是CalendarView,当我将其移除时,速度恢复正常(即:瞬间)。我想问题可能与我请求Android进行布局的方式有关,可能不太合理或效率低下之类的。

以下是XML文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp">

<TextView
     android:id="@+id/title"
     android:layout_width="0dp"
     android:layout_height="wrap_content"
     android:textStyle="bold"
     android:text="TODAY"
     android:textAppearance="?android:attr/textAppearanceLarge" 

     android:layout_alignParentLeft="true"
     android:layout_alignParentTop="true"
     android:layout_toLeftOf="@+id/time" />

<TextView
     android:id="@id/time"
     android:gravity="right"
     android:textStyle="bold"
     android:layout_width="100dp"
     android:layout_height="wrap_content"
     android:text="11:32"
     android:textAppearance="?android:attr/textAppearanceLarge"

     android:layout_alignParentRight="true" />

<TextView
    android:id="@+id/date_info"
    android:layout_margin="20dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Wednesday, 15th August 2012"
    android:textAppearance="?android:attr/textAppearanceMedium"

    android:layout_below="@id/title"
    android:layout_alignParentLeft="true" />

<CalendarView        
    android:id="@+id/calendar_view"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:background="@drawable/white_back_black_border"

    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true" />
</RelativeLayout>

我尝试了很多不同的布局选项,但似乎只有删除日历才会有所改变。

非常感谢任何见解。 谢谢


你在代码中使用日历视图做了什么吗?比如设置日期等。 - Warpzit
即使我注释掉所有与它相关的代码,它仍然很慢。但是一旦我从布局文件中删除它,问题就解决了。我认为这一定与RelativeLayout有关,因为如果我记得正确的话,当我使用LinearLayout时,它运行良好... - carlmango11
好的,就这样吧。这根本没有任何意义。我猜可能是其他原因。 - Warpzit
我知道这很奇怪。只是为了确保,我刚刚将它切换到LinearLayout上。工作正常,加载速度很快。我想暂时可以使用LinearLayout,但它仍然让我感到烦恼。 - carlmango11
这个人有同样的问题:如何停止Android 2.3.3中的垃圾回收 - Salvatorelab
6个回答

6
我也遇到了这个问题,无论是相对布局还是线性布局,都存在此问题。这似乎与布局无关。
以下是一个例子,可以看到错误,只需使用简单的布局,而不需要任何代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".FechaHoraActivity" >

    <TimePicker
        android:id="@+id/timePicker1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20dp" />

    <CalendarView
        android:id="@+id/calendarView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

现在只需将线性布局的高度更改为:

android:layout_height="match_parent"

通过这个更改,问题已经解决了,至少在我的三星Galaxy Tab 2上是这样。

所以看起来这更多地与“空间”有关,但我仍然不确定为什么会出现这个问题。在谷歌搜索“calendarview slow”时,我没有找到任何其他有趣的结果...

编辑 让我们看看是否可以通过小额赏金找到答案


CalendarViewlayout_height 也需要设置为 match_parent - faizal

5
我花了几个小时寻找答案,但仍然找不到原因。有些奇怪的事情,也许可以帮助你找到答案。
当CalendarView变慢时,CPU使用率很高(见下图):

enter image description here

WeekAdapter中的getView方法有一个未被使用的parent参数。
   public View getView(int position, View convertView, ViewGroup parent) {
       WeekView weekView = null;
        if (convertView != null) {
            weekView = (WeekView) convertView;
        } else {
            weekView = new WeekView(mContext);
            android.widget.AbsListView.LayoutParams params =
                new android.widget.AbsListView.LayoutParams(LayoutParams.WRAP_CONTENT,
                        LayoutParams.WRAP_CONTENT);
            weekView.setLayoutParams(params);
            weekView.setClickable(true);
            weekView.setOnTouchListener(this);
        }

        int selectedWeekDay = (mSelectedWeek == position) ? mSelectedDate.get(
                Calendar.DAY_OF_WEEK) : -1;
        weekView.init(position, selectedWeekDay, mFocusedMonth);

        return weekView;
    }

期待您的回答。


你如何查看CPU的使用情况?这是在Eclipse中吗? - Nick
看看这个,它已经集成在DDMS中了。 - Everett
有趣,我们现在更接近了。我已经使用了你的方法来比较两个布局(请参见我的答案)。第一个(挂起的):wrap_content和运行良好的一个:match_parent。正如你所看到的,差异从第4个开始,“obtainView”。在里面,我们可以看到:inside obtainView是的,WeekAdapter.getView显然是问题所在,你是对的,现在我们必须找出原因。 - Salvatorelab
我们仍然不知道为什么会发生这种情况,但是你进行了出色的调查,我不想空手而归,所以请享受这份奖励 =) - Salvatorelab
谢谢TheBronx,这个谜题仍然未解决,任何能够解决的人都将得到奖励。 - Everett
遇到了相同的问题。SDK 4.2。 - drdrej

3

似乎在RelativeLayout内直接使用CalendarView无法正常工作。以下解决方案使用FrameLayout的技巧,在模拟器中加载速度更快:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp" >

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_toLeftOf="@+id/time"
        android:text="TODAY"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textStyle="bold" />

    <TextView
        android:id="@id/time"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:gravity="right"
        android:text="11:32"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/date_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/title"
        android:layout_margin="20dp"
        android:text="Wednesday, 15th August 2012"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <FrameLayout
        android:layout_width="250dp"
        android:layout_height="250dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true" >

        <CalendarView
            android:id="@+id/calendar_view"
            android:layout_width="250dp"
            android:layout_height="250dp"
            android:background="@drawable/white_back_black_border" />
    </FrameLayout>
</RelativeLayout>

并不是 FrameLayout 解决了问题,而是固定高度。似乎 Android 需要高度才能顺利构建周… - Salvatorelab
1
我再次进行了测试,使用RelativeLayout而不是FrameLayout,应用程序加载需要+10秒。我将calendarView的周围布局更改回FrameLayout,它再次立即加载。因此,我倾向于认为这绝对与RelativeLayout处理CalendarViews的方式有关。 - Mirco Widmer
是的,相对布局在渲染日历视图时有些问题。可以使用线性布局代替...感谢兄弟的帮助,我支持你 +1。 - Naruto

3
发现CalendarView小部件需要将高度设置为match_parent,然后可以将它放置在任何布局中。例如,与高度为200的相对布局。这在4.0.3模拟器和搭载4.2.2版本的三星Galaxy Tab上运行良好。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true" >

        <CalendarView
            android:id="@+id/cv_dialog_filter_date"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </RelativeLayout>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/relativeLayout2"
        android:layout_centerHorizontal="true"
        android:text="05.12.2013" />

</RelativeLayout>

2
将CalendarView放在FrameLayout中可以解决这个问题。以下是XML代码示例:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cc00b1cc">

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="102dp"
        android:layout_alignParentBottom="true">

        <CalendarView
            android:layout_width="425dp"
            android:layout_height="374dp"
            android:id="@+id/calendarView"
            android:layout_gravity="left|top" />
    </FrameLayout>
</RelativeLayout>

0

以上的答案都是正确的,但仍未解决一个谜团。

那就是,当我想在其他布局中包含日历视图时,它就会消失或者我只能看到星期几的字母。我尝试了上面的match parent和其他一切方法,但仍然无法解决它。

如果有人像我一样苦苦挣扎,这里有答案。

   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">


<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <CalendarView
        android:id="@+id/calendarService"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/linearLayout"></CalendarView>

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical"> 


     ///Your views 


     />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接