Android ListView创建和绑定很慢

时间:2014-03-17 07:34:41

标签: android xml performance android-layout listview

我(和其他许多人一样)在listview中获得顺畅的性能时遇到了问题。我相信我已经完成了本书的所有工作,但每次在屏幕上绘制新项目时,它仍然会显着滞后(约300-500毫秒)。

我正在使用viewHolder并尽可能多地重用UI元素(我认为)。有两个明确的瓶颈。

  1. 第一个是在newView()方法中膨胀XML代码的行。那是因为某种原因真的很慢(约300毫秒),我不知道这是否是预期的。

  2. 其次,bindView需要很长时间才能执行。这只是因为TextView.setText()方法调用占用了所有时间。 Other people have had the same problem我确实知道如果Android需要为每个列表项重新测量整个UI,这可能会很慢。但是,在将XML文件TextViews更改为固定大小后,我仍然会从.setText()获得非常慢的性能。我知道我可以将.setText放在Handler中,但在这种情况下看起来像是一个黑客。我会阻止列表滞后,但它不会更快地添加文本。我相信我应该能够将文本设置为快于~400毫秒,如果需要这么长时间我的UI /逻辑有问题。

  3. 但是如果没有进一步的麻烦,我会向您介绍源代码:希望能够巧妙地了解我做错了什么。

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    
        if (ApplicationConfiguration.DEBUGGING)
            Debug.startMethodTracing("getview");
    
        View listViewItem;
        EpisodeViewHolder holder;
    
        Cursor itemCursor = (Cursor) getItem(position);
    
        if (!itemCursor.moveToPosition(position)) {
            throw new IllegalStateException("couldn't move cursor to position "
                    + position);
        }
    
        mCurrentFeedItem = MyListItem.getByCursor(itemCursor);
        int type = getItemViewType(position);
    
        if (convertView == null) {
            switch (type) {
            case TYPE_EXPAND:
                listViewItem = newView(mContext, itemCursor, parent);
                break;
    
            default:
                listViewItem = newView(mContext, itemCursor, parent);
                break;
            }
        } else {
            listViewItem = convertView;
        }
    
        bindView(listViewItem, mContext, itemCursor);
    
        switch (type) {
        case TYPE_EXPAND:
            getPlayerViewHolder(position, listViewItem, itemCursor,
                    convertView, parent);
        }
    
        if (ApplicationConfiguration.DEBUGGING)
            Debug.stopMethodTracing();
    
        return listViewItem;
    }
    

    这是我的新视图

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
    
        View view = mInflater.inflate(R.layout.episode_list, null); // here is the bottleneck
    
        EpisodeViewHolder holder = new EpisodeViewHolder();
        holder.icon = (ImageView) view.findViewById(R.id.list_image);
        holder.mainTitle = (TextView) view.findViewById(R.id.title);
        holder.subTitle = (TextView) view.findViewById(R.id.podcast);
        holder.timeDuration = (TextView) view.findViewById(R.id.duration);
        holder.currentPosition = (TextView) view.getTag(R.id.current_position);
        holder.slash = (TextView) view.findViewById(R.id.time_slash);
        holder.fileSize = (TextView) view.findViewById(R.id.filesize);
        holder.stub = (ViewStub) view.findViewById(R.id.stub);
        holder.playerView = (View) view.findViewById(R.id.stub_player);
        view.setTag(holder);
    
        return view;
    }
    

    我的bindView方法很长,但我会稍微缩短一下

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        .....
       final EpisodeViewHolder holder = (EpisodeViewHolder) view.getTag();
        .....
        // not a bottleneck
        // Loads the image Async. The synchronous part of the call takes around 10%
        // of the entire method
        PicassoWrapper.load(mContext, i, holder.icon);
    
         // This is the bottleneck
        holder.mainTitle.setText(title);
        }
    

    XML UI

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
    
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:orientation="horizontal" >
    
            <LinearLayout
                android:id="@+id/thumbnail"
                android:layout_width="wrap_content"
                android:layout_height="fill_parent"
                android:layout_alignParentLeft="true"
                android:layout_marginRight="7dip"
                android:padding="0dip" >
    
                <ImageView
                    android:id="@+id/list_image"
                    style="@style/PodcastImage" />
            </LinearLayout>
    
            <TextView
                android:id="@+id/title"
                style="@style/EpisodeHeaderFont"
                android:layout_width="200dp"
                android:layout_height="40dp"
                android:layout_alignTop="@+id/thumbnail"
                android:layout_toRightOf="@+id/thumbnail"
                android:text="Podcast Title" />
    
            <TextView
                android:id="@+id/podcast"
                android:layout_width="200dp"
                android:layout_height="40dp"
                android:layout_above="@+id/current_position"
                android:layout_below="@id/title"
                android:layout_marginTop="1dip"
                android:layout_toRightOf="@+id/thumbnail"
                android:ellipsize="end"
                android:text="Podcast Name"
                android:textSize="10dip" />
    
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true" />
    
            <TextView
                android:id="@+id/current_position"
                style="@style/EpisodeMinorFont"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBottom="@+id/thumbnail"
                android:layout_toRightOf="@+id/thumbnail" />
    
            <TextView
                android:id="@+id/time_slash"
                style="@style/EpisodeMinorFont"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBaseline="@+id/current_position"
                android:layout_alignBottom="@+id/current_position"
                android:layout_toRightOf="@+id/current_position"
                android:paddingLeft="5dip"
                android:paddingRight="5dip"
                android:visibility="gone" />
    
            <TextView
                android:id="@+id/duration"
                style="@style/EpisodeMinorFont"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignBaseline="@+id/time_slash"
                android:layout_alignBottom="@+id/time_slash"
                android:layout_toRightOf="@+id/time_slash" />
    
            <TextView
                android:id="@+id/filesize"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignBottom="@+id/duration"
                android:layout_toRightOf="@+id/duration"
                android:gravity="bottom|right"
                android:text="0"
                android:textSize="10dip"
                android:textStyle="bold" />
        </RelativeLayout>
    
        <FrameLayout
            android:id="@id/drag_handle"
            android:layout_width="25dp"
            android:layout_height="match_parent"
            android:paddingBottom="30dp"
            android:paddingTop="30dp" >
    
            <LinearLayout
                android:layout_width="7dp"
                android:layout_height="fill_parent"
                android:background="@drawable/drag_handle"
                android:orientation="vertical"
                android:tileMode="repeat" >
    
            </LinearLayout>
        </FrameLayout>
    </LinearLayout>
    
    <ViewStub
        android:id="@+id/stub"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inflatedId="@+id/stub_player"
        android:layout="@layout/list_item_expanded" />
    

0 个答案:

没有答案