AnR警告Android上的布局时间太长 [英] ANR warning onLayout time too long on Android

查看:0
本文介绍了AnR警告Android上的布局时间太长的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直致力于开发应用程序。在构建我的应用程序时,我得到了On Layout Time Too Long Layout Time Too Layout Time Too Long和LogCAT警告。所以我的问题是,到底是什么问题?

ANR Warning]onLayout time too long, this =android.widget.FrameLayout{b7ebc83 V.E...... ......ID 0,0-720,1200 #7f0b005f app:id/content}time =651 ms
 D/View: [ANR Warning]onLayout time too long, this =android.widget.LinearLayout{2b85e00 V.E...... ......ID 0,0-720,1200}time =652 ms
 D/View: [ANR Warning]onLayout time too long, this =android.widget.FrameLayout{9243639 V.E...... ......ID 0,96-720,1296 #7f0b0065 app:id/view_content}time =652 ms
 D/View: [ANR Warning]onLayout time too long, this =android.widget.LinearLayout{606a47e V.E...... ......ID 0,0-720,1296}time =654 ms
 D/View: [ANR Warning]onLayout time too long, this =android.support.v7.widget.ContentFrameLayout{e669ddf V.E...... ......ID 0,0-720,1296 #1020002 android:id/content}time =654 ms
 D/View: [ANR Warning]onLayout time too long, this =android.support.v7.widget.FitWindowsLinearLayout{f455a2c V.E...... ......ID 0,0-720,1296 #7f0b004b app:id/action_bar_root}time =655 ms
 D/View: [ANR Warning]onLayout time too long, this =android.widget.FrameLayout{c08fcf5 V.E...... ......ID 0,48-720,1344}time =655 ms 
 D/View: [ANR Warning]onLayout time too long, this =android.widget.LinearLayout{7648a8a V.E...... ......ID 0,0-720,1344}time =656 ms
 D/View: [ANR Warning]onLayout time too long, this =DecorView@23d1963[MainActivity]time =656 ms

以下是我遇到上述问题的应用程序布局文件

Fragment_Video_Browser.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_video"
    android:layout_width="match_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view1_video"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />
    <!--/>-->
    <!--android:background="@color/novided_bg"-->
</LinearLayout>

active_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"/>

ACTIVATION_TITLE_base.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/toolbar_height"
        android:background="?attr/colorPrimary"
        android:fitsSystemWindows="true"
        app:contentInsetEnd="0dp"
        app:contentInsetStart="0dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/toolbar_height"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView
                android:id="@+id/back"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/toolbar_backmenu_margin_start"
                android:background="?android:attr/actionBarItemBackground"
                android:clickable="true"
                android:src="@mipmap/back"
                android:visibility="invisible" />

            <TextView
                android:id="@+id/title_text"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:lines="1"
                android:textColor="@color/toolbar_title_color"
                android:textDirection="locale"
                android:textSize="@dimen/toolbar_title_size" />

            <ImageView
                android:id="@+id/menu"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginEnd="@dimen/toolbar_menu_marginend"
                android:background="?android:attr/actionBarItemBackground"
                android:clickable="true"
                android:paddingEnd="@dimen/toolbar_menu_padding"
                android:paddingStart="@dimen/toolbar_menu_padding"
                android:src="@drawable/ic_more"
                android:visibility="gone"/>

            <ImageView
                android:id="@+id/edit"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginEnd="@dimen/toolbar_menu_marginend"
                android:background="?android:attr/actionBarItemBackground"
                android:clickable="true"
                android:paddingEnd="@dimen/toolbar_menu_padding"
                android:paddingStart="@dimen/toolbar_menu_padding"
                android:src="@drawable/ic_btn_edit"
                android:visibility="gone" />

            <TextView
                android:id="@+id/all_select"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="@dimen/toolbar_selectall_margin_end"
                android:background="?android:attr/selectableItemBackgroundBorderless"
                android:textColor="@color/toolbar_selectall_color"
                android:textDirection="locale"
                android:textSize="@dimen/toolbar_selectall_textsize"
                android:visibility="gone" />
        </LinearLayout>
    </android.support.v7.widget.Toolbar>

    <FrameLayout
        android:id="@+id/view_content"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

Fragment.java

public class VideoBrowserFragment extends BaseFragment implements LoaderManager.LoaderCallbacks<Cursor>,
        VideoBrowserAdapter.OnRecyclerViewItemClickListener,
        VideoBrowserAdapter.OnItemLongClickListener,
        EditionMode.OnEditionModeListener {

    public final static String TAG = "Video/VideoBrowserFragment";
    private int defaultSort = MediaInfoComparator.SORT_BY_NAME;
    protected VideoBrowserAdapter mAdapter;
    private VideoBrowserData videoMedia;
    private View view;
    private String bucketID;
    private String bucketName;
    private UiHanlder uiHanlder = new UiHanlder();

    private class UiHanlder extends Handler {
        @Override
        public void handleMessage(final Message msg) {
            ((BaseActivity) getActivity()).onBackPressed();
        }
    }

    @Override
    public boolean onBackPressed() {
        if (editionMode != null) {
            if (editionMode.inEdionModle) {
                editionMode.leaveEdition();

                if (videoMedia != null && videoMedia.videoArrayList.size() == 0) {
                    return false;
                } else {
                    return true;
                }
            }
        } else {
            this.onDestroy();
        }
        return false;
    }

    @Override
    public boolean inEditModel() {
        if (editionMode == null) {
            return false;
        }
        if (editionMode.inEdionModle) {

            if (editionMode.selectionManager.getCheckedItemsCount() == mAdapter.getItemCount()) {
                editionMode.allNotSelect();
            } else {
                editionMode.allSelect((ArrayList<VideoInfoBean>) videoMedia.videoArrayList.clone());
            }

        } else {
            editionMode.inEdition();
        }
        return false;
    }

    @Override
    public boolean sortByType(int type) {
        if (videoMedia == null) {
            return false;
        }
        sortData(type);
        defaultSort = type;
        return false;
    }

    private void sortData(int type) {
        Collections.sort(videoMedia.videoArrayList, MediaInfoComparator.getInstance(type));
        mAdapter.setData(videoMedia.videoArrayList);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Bundle bundle = getArguments();
        if (bundle != null) {
            bucketID = bundle.getString(FileBrowserFragment.BUCKETID);
            bucketName = bundle.getString(FileBrowserFragment.BUCKETNAME);
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Log.d("MY_LOG", "vdo FRAGMENT started");

        super.onCreateView(inflater, container, savedInstanceState);
        view = inflater.inflate(R.layout.fragment_video_browser, container, false);
        init();
        Log.d("MY_LOG", "vdo FRAGMENT ended");
        return view;
    }

    private void init() {
        ((BaseActivity) getActivity()).setTitleText(bucketName);
        ((BaseActivity) getActivity()).setBackVisible();
        ((BaseActivity) getActivity()).setAllSelectVisible(View.GONE);
        ((BaseActivity) getActivity()).setEditVisible(View.GONE);
        ((BaseActivity) getActivity()).setMenuVisible(View.VISIBLE);

        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this.getContext());
        layoutManager.setAutoMeasureEnabled(false);
        mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view1_video);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setItemViewCacheSize(20);
        mRecyclerView.setDrawingCacheEnabled(true);


        mRecyclerView.setDrawingCacheBackgroundColor(View.DRAWING_CACHE_QUALITY_HIGH);
        mRecyclerView.setLayoutManager(layoutManager);
        mAdapter = new VideoBrowserAdapter(this.getContext());
        mAdapter.mThumbnailCache = new ThumbnailCache(getContext());

        mRecyclerView.setAdapter(mAdapter);
//        mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL_LIST));
//        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

        mAdapter.setOnItemClickListener(this);
        mAdapter.setOnItemClickLongListener(this);
        getLoaderManager().initLoader(1, null, this);

        editionMode = new EditionMode(this, (BaseVideoActivity) this.getActivity(), mAdapter, getContext(), view, R.id.fragment_video);
        editionMode.setOnEditionModeListener(this);
        mAdapter.mActionMode = editionMode;
        mAdapter.mThumbnailCache.addListener(mAdapter);
    }


    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        videoMedia = new VideoBrowserData(this.getContext());
        return videoMedia.getCursorLoader(bucketID);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        if (videoMedia == null) {
            videoMedia = new VideoBrowserData(this.getContext());
        }

        if (data != null && videoMedia != null) {
            videoMedia.queryAllVideo(data);
            setPlayInfo();
            sortData(defaultSort);
            if (editionMode.inEdionModle) {
                editionMode.refreshCheckedItem((ArrayList<VideoInfoBean>) videoMedia.videoArrayList.clone());
                editionMode.updateAllSize();
            }

            if (videoMedia.videoArrayList.size() == 0) {
                uiHanlder.sendEmptyMessage(0);
            }
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

    }

    @Override
    public void onResume() {
        super.onResume();
        if (videoMedia == null) {
            getLoaderManager().restartLoader(0, null, this);
            return;
        }
        setPlayInfo();
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void onDestroy() {
        Log.d("onDestroy", "onDestroy");
        if (mAdapter != null) {
            mAdapter.clearCachedHolder();
            if (mAdapter.mThumbnailCache != null) {
                mAdapter.mThumbnailCache.clear();
                mAdapter.mThumbnailCache = null;
            }
        }
        getLoaderManager().destroyLoader(1);
        super.onDestroy();
    }

    @Override
    public void onItemClick(View view, RecyclerView.ViewHolder data) {


        Log.i(TAG, "onItemClick video : inEdionModle:" + editionMode.inEdionModle);
        final Object obj = view.getTag();
        int index = 0;
        if (obj == null || !(obj instanceof RecyclerView.ViewHolder)) {
            return;
        }
        if (editionMode.inEdionModle) {
            editionMode.select((VideoBrowserAdapter.VideoViewHolder) obj);
        } else {
            for (int i = 0; i < videoMedia.videoArrayList.size(); i++) {
                if (((BaseAdapter.VideoViewHolder) data).mId == videoMedia.videoArrayList.get(i).mediaID) {
                    index = i;
                    break;
                }
            }
            VideoActivity.startPlayVideoList(getActivity(), index, videoMedia.videoArrayList);
        }

    }

    @Override
    public void onItemLongClick(View view, RecyclerView.ViewHolder data) {
        final Object obj = view.getTag();
        if (obj == null || !(obj instanceof RecyclerView.ViewHolder)) {
            return;
        }
        editionMode.inEditionSelect((VideoBrowserAdapter.VideoViewHolder) obj);
    }

    public void setPlayInfo() {
        for (int i = 0; i < videoMedia.videoArrayList.size(); i++) {
            VideoInfoBean videoInfoBean = videoMedia.videoArrayList.get(i);
            float index = VideoActivity.getLastPlayedVidePosition(videoInfoBean.mediaPath);
            if (index == 0.0) {
                videoInfoBean.playIndex = null;
            } else {
                videoInfoBean.playIndex = Utils.getIndex(index);
            }

            if (VideoActivity.getLastPlayedVideo() != null) {
                if (VideoActivity.getLastPlayedVideo().equals(String.valueOf(videoInfoBean.mediaPath))) {
                    videoInfoBean.isLastPlay = true;
                } else {
                    videoInfoBean.isLastPlay = false;
                }
            }

        }

    }

    @Override
    public int getAllSize() {
        return videoMedia.videoArrayList.size();
    }
}

编辑:将回收器视图的布局高度降低到300dp时,我没有收到警告。

推荐答案

从您的布局来看,除了Fragment_Video_Browser的LinearLayout中的Fill_Parent之外,其他一切似乎都很好。

这就是你所有问题的根源,fill_parent,现在被Match_Parent取代在Android文档中有这样的描述;

Fill_Parent(在API级别8及更高版本中重命名为Match_Parent),这意味着视图希望与其父视图一样大(减去填充)

如果您的线性布局不断地扩展其高度,并且其子对象RececumerView的高度属性为Match_Parent,则达到最大可用高度的竞赛永远不会到达终点,直到RececurerView中的所有项目都已准备就绪-尽管没有显示。

在此级别上,拥有RececurerView的意义变得毫无意义,因为它的主要功能是在用户滚动时回收项目,但当它一次准备所有项目时,它只是作为一个静态视图,需要一些时间才能准备好。

从您的编辑,

将回收器视图的布局高度降低到300dp时,我没有收到警告。

它清楚地说明,如果您将高度限制为该值,RececumerView适配器只准备足够在该视口中显示的项目,这很快,然后当您滚动时,会根据滚动方向准备更多项目。

一种快速的解决方法是消除对最大可用高度的追求,并在回收器中使用WRAP_CONTENT。

其他原因包括在NestedScrollView以及具有可展开/可滚动视图的任何其他视图中嵌套RececurerView,而不注意为RececurerView提供的高度参数。

这里是文档中的一个示例,说明如何利用RececumerView来实现其功能。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/list_item_height"
android:layout_marginLeft="@dimen/margin_medium"
android:layout_marginRight="@dimen/margin_medium"
android:gravity="center_vertical">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/element_text"/>

如果项目较少,则不会遇到此ANR问题,但随着列表的增加,例如接近100个或更多项目,您将开始遇到此问题。

要确定在调整布局参数后是否已修复此问题,一个简单的测试是记录在该覆盖内的onBindViewHolder中绑定的项,如下所示:

Log.d("TAG", "Binding item at position $position")

如果一切正常,该函数将在您滚动时以位为单位打印输出,但如果它一次打印所有项目,则您尚未解决问题-假设您的所有项目无法在一个屏幕上显示,需要滚动以获得更多。

阅读有关docs的更多信息。

这篇关于AnR警告Android上的布局时间太长的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆