【问题标题】:Scroll View and memory leaks滚动视图和内存泄漏
【发布时间】:2013-11-29 20:46:29
【问题描述】:

我的滚动视图出现记忆问题。我有一个新闻列表和显示完整新闻信息的活动。这是我的布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/lightgrey"
    android:paddingBottom="8dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:paddingTop="8dp"
    tools:context=".ViewNewsActivity" >

<ScrollView
    android:id="@+id/scroll_news"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:background="@color/lightgrey"
    android:isScrollContainer="false" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/ivIconFull"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/icon_bg"
            android:src="@drawable/nophotobig_hdpi_two" />

        <TextView
            android:id="@+id/tv_news_title_full"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.20"
            android:background="@color/dark_grey_one"
            android:paddingBottom="8dp"
            android:paddingLeft="12dp"
            android:paddingRight="8dp"
            android:paddingTop="8dp"
            android:text="@string/example_title"
            android:textColor="@color/white"
            android:textSize="16sp" />

        <TextView
            android:id="@+id/tv_news_date_full"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/dark_grey_one"
            android:paddingBottom="8dp"
            android:paddingLeft="12dp"
            android:paddingRight="8dp"
            android:paddingTop="8dp"
            android:text="@string/example_date"
            android:textColor="@color/lightgrey"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/tv_news_text_full"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:background="@color/white"
            android:paddingBottom="8dp"
            android:paddingLeft="12dp"
            android:paddingRight="8dp"
            android:paddingTop="8dp"
            android:text="@string/example_title"
            android:textColor="@color/dark_grey_one"
            android:textSize="16sp" />

        <LinearLayout
            android:id="@+id/llVideo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:background="@color/lightgrey"
            android:orientation="vertical" />

        <FrameLayout
            android:id="@+id/fragment_photo_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="4dp"
            android:background="@color/lightgrey" />

        <Button
            android:id="@+id/btn_write_comennts"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="20dp"
            android:background="@drawable/btn_green"
            android:onClick="onWriteCommentClick"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:text="@string/write_comment"
            android:textColor="@color/white" />

        <FrameLayout
            android:id="@+id/fragment_comments_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:background="@color/lightgrey" />

        <Button
            android:id="@+id/btn_read_comennts"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="20dp"
            android:background="@drawable/btn_gray"
            android:onClick="onReadCommentClick"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:text="@string/all_comments"
            android:textColor="@color/white" />
    </LinearLayout>
</ScrollView>

</RelativeLayout>

这是活动类

public class ViewNewsActivity extends SherlockFragmentActivity {
News news;
Context ctx;
Button btnReadComment;
int commentsCount;
double k;
boolean isTablet;
ScrollView scroll;
ImageView ivIcon;
Picasso picasso;
SherlockFragment frag;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT < 14) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
    }
    setTheme(R.style.Theme_CIS_NORMAL);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    setContentView(R.layout.activity_view_news);
    Gson gson = new Gson();
    Type newsType = new TypeToken<News>() {
    }.getType();
    news = gson.fromJson(getIntent().getStringExtra(AppConst.CHOOSEN_NEWS),
            newsType);
    // Set title style------------------------------

    SpannableString title = new SpannableString(news.getName());
    title.setSpan(new TypefaceSpan(this, "robotregular"), 0,
            title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

    // ----------------------------------------------------------------
    getSupportActionBar().setTitle(title);
    // getSupportActionBar().setIcon(R.drawable.ic_ab);
    getSupportActionBar().setHomeButtonEnabled(true);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    ctx = this;
    isTablet = getResources().getBoolean(R.bool.isTablet);
    BusProvider.getInstance().register(this);
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    FragmentHelper fHelper = new FragmentHelper(
            (SherlockFragmentActivity) ctx);
    int w = metrics.widthPixels;
    k = 8 * DeviceDensity.getDensity(ctx);

    // init all components
    commentsCount = news.getCommentsCount();
    scroll = (ScrollView) findViewById(R.id.scroll_news);
    scroll.clearDisappearingChildren();
    ivIcon = (ImageView) findViewById(R.id.ivIconFull);
    TextView tvTitle = (TextView) findViewById(R.id.tv_news_title_full);
    TextView tvDate = (TextView) findViewById(R.id.tv_news_date_full);
    TextView tvText = (TextView) findViewById(R.id.tv_news_text_full);
    // new FullImageLoader(ivIcon).execute(news.getSmallIcon());
    Picasso.Builder builder = new Picasso.Builder(ctx);
    picasso = builder.build();
    picasso.load(news.getSmallIcon())
            .placeholder(
                    PlaceHolders.getInstanse().getPlaceHolder(
                            (int) (w - (k * 2)),
                            (int) ((w - (k * 2)) / 1.5)))

            .error(PlaceHolders.getInstanse().getPlaceHolder(
                    (int) (w - (k * 2)), (int) ((w - (k * 2)) / 1.5)))
            .resize((int) (w - (k * 2)), (int) ((w - (k * 2)) / 1.5))
            .into(ivIcon);
    tvTitle.setTypeface(TypefaceCache.get(getAssets(),
            "fonts/robotregular.ttf"));
    tvTitle.setText(news.getName());
    tvDate.setTypeface(TypefaceCache.get(getAssets(),
            "fonts/robotregular.ttf"));
    tvDate.setText(news.getDate() + " / " + news.getCatName());
    tvText.setTypeface(TypefaceCache.get(getAssets(),
            "fonts/robotregular.ttf"));
    tvText.setText((news.getText()).replaceAll("&quot;", "\""));
    if (news.isNewsWithVideo()) {
        LinearLayout videoContainer = (LinearLayout) findViewById(R.id.llVideo);
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View video = inflater.inflate(R.layout.video, null);
        ImageView videoIcon = (ImageView) video
                .findViewById(R.id.ivVideoContainer);
        ImageButton btnPlay = (ImageButton) video
                .findViewById(R.id.ibPlayVideo);
        btnPlay.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                startActivity(new Intent(ViewNewsActivity.this,
                        YouTubeActivity.class).putExtra(AppConst.VIDEO_ID,
                        news.getVideoId()));
            }
        });
        picasso.load(
                "http://img.youtube.com/vi/" + news.getVideoId() + "/0.jpg")
                .placeholder(
                        PlaceHolders.getInstanse().getPlaceHolder(
                                (int) (w - (k * 2)),
                                (int) ((w - (k * 2)) / 1.5)))
                .error(PlaceHolders.getInstanse().getPlaceHolder(
                        (int) (w - (k * 2)), (int) ((w - (k * 2)) / 1.5)))
                .resize((int) (w - (k * 2)), (int) ((w - (k * 2)) / 1.5))
                .into(videoIcon);
        videoContainer.addView(video);
    }
    // --------------------------------------------------------------

    if (news.isNewsWithPhoto()) {



        if (news.getPhotoUrls().size() > 4) {

            frag = new NewsPhotoFragment();

        } else {
            if ((isTablet || Math.round(DeviceDensity.getInches(ctx)) >= 5)
                    && news.getPhotoUrls().size() > 1) {
                frag = new NewsAlbumListBigFragment();
            } else {
                frag = new NewsAlbumListFragment();
            }
        }
        Bundle b = new Bundle();
        b.putStringArrayList(AppConst.PHOTO_ALBUM,
                (ArrayList<String>) news.getPhotoUrls());
        fHelper.addFragmentWhithBundle(R.id.fragment_photo_container, frag,
                b);
    }

    // ----------------------------------------------------------------
    btnReadComment = (Button) findViewById(R.id.btn_read_comennts);
    if (news.isNewsCommented()) {
        if (commentsCount >= 5) {
            btnReadComment.setText(getResources().getString(
                    R.string.all_comments)
                    + " (" + news.getCommentsCount() + ")");
        } else {
            btnReadComment.setVisibility(Button.GONE);
        }

        Bundle b = new Bundle();
        CommentsFragment cFrag = new CommentsFragment();
        b.putString(AppConst.API_COMMENTS_PAGE_ID,
                Long.toString(news.getId()));
        fHelper.addFragmentWhithBundle(R.id.fragment_comments_container,
                cFrag, b);
    } else {
        Button btnWriteComment = (Button) findViewById(R.id.btn_write_comennts);

        btnWriteComment.setVisibility(Button.GONE);
        btnReadComment.setVisibility(Button.GONE);
    }

}

@Override
public void onDestroy() {
    super.onDestroy();
    scroll.removeAllViews();
    news = null;
    picasso.shutdown();
    picasso = null;
    ctx = null;
    frag = null;
    System.gc();

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    menu.add(0, AppConst.SHARE_ID, Menu.NONE, "Поделиться")
            .setIcon(R.drawable.ic_share_x)

            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    if (news.isNewsCommented() && commentsCount >= 5) {
        menu.add(0, AppConst.COMMENTS_ID, Menu.NONE, "Коментарии")
                .setIcon(R.drawable.chat_x)

                .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    }
    return true;
}

// press action bar menu items
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home) {
        finish();
    } else if (item.getItemId() == AppConst.SHARE_ID) {
        final Intent intent = new Intent(Intent.ACTION_SEND);
        intent.setType("text/plain");
        intent.setAction(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TEXT,
                news.getName() + " " + news.getNewsUrl());

        startActivity(Intent.createChooser(intent,
                getString(R.string.shareNews)));
    } else if (item.getItemId() == AppConst.COMMENTS_ID) {
        startActivity(new Intent(ViewNewsActivity.this,
                AllCommentsActivity.class).putExtra(AppConst.NEWS_ID,
                news.getId()).putExtra(AppConst.CHOOSEN_NEWS,
                news.getName()));
    }
    return true;
}

public void onWriteCommentClick(View v) {
    // write comments activity
    startActivity(new Intent(ViewNewsActivity.this,
            WriteCommentActivity.class).putExtra(AppConst.NEWS_ID,
            news.getId()).putExtra(AppConst.CALLED_FROM,
            AppConst.COMMENTS_FROM_VIEW_NEWS));
}

public void onReadCommentClick(View v) {
    // read all comments activity
    startActivity(new Intent(ViewNewsActivity.this,
            AllCommentsActivity.class).putExtra(AppConst.NEWS_ID,
            news.getId()).putExtra(AppConst.CHOOSEN_NEWS, news.getName()));
}

@SuppressLint("NewApi")
@Subscribe
public void onShouldUpdateCommentsCount(OnShouldUpdateCommentsInNews event) {
    commentsCount++;
    if (commentsCount >= 5) {
        btnReadComment.setVisibility(Button.VISIBLE);
        btnReadComment.setText(getResources().getString(
                R.string.all_comments)
                + " (" + commentsCount + ")");
        invalidateOptionsMenu();
    }
}
}

我试图清除一切,但我的记忆像地狱一样长大!!!而且在我完成这个活动后,内存并没有清除,很快我就出现了内存不足的异常!

我真的不知道我要做什么!也许我应该使用其他东西而不是滚动视图?

【问题讨论】:

  • 我会按照 Egor 的建议使用 MAT 查看堆转储。您似乎不是以传统方式使用毕加索,它可能与它有关。试试 Picasso.with(this).load(url).into(imageView);你可以将你的 .resize() 等链接在他们的.resize() 中。无需为它保留参考。
  • 您可以尝试的一件事是制作 ctx = this.getApplicationContext() 并查看是否可以解决问题。内存泄漏是由于将 Activity 上下文从 Activity 传递给比 Activity 的生命周期更长的东西而引起的
  • 我以这种方式使用 Picasso,没有任何帮助,我无法使用单例调用 picasso.shutdown()(此方法调用 memoryCache.clear()),所以我决定做这样的事情。我在我所有的适配器中都使用毕加索,我在网格视图和列表视图中下载了大量的图像,我没有任何问题,这就是为什么我认为问题出在滚动视图中。但我会尝试 MAT,也许它会有所帮助......
  • 当然!我也会尝试,我的片段中有一个问题我使用来自 onAttach(Activity a){ctx = activity} 的上下文,我是否以正确的方式使用它?
  • 如果 Fragment 以某种方式比 Activity 寿命更长,它肯定会导致整个 Activity 泄漏。主要问题之一是匿名类或内部类,它们的寿命可能比封闭类长。如果您在 Fragment 中有任何这些,请看那里。

标签: android memory-leaks scrollview out-of-memory


【解决方案1】:

我很确定您的内存泄漏与您尝试下载的视频拇指的图像有关。您需要实现某种惰性图像加载器。只需在 Google 上搜索该术语,您就会找到一两个可以为您完成所有这些工作的库。

【讨论】:

  • 他有一个懒惰的图像加载器,毕加索
【解决方案2】:

Here's 一篇非常有用的文章,描述了 MAT - 一种可以帮助您发现应用程序中的内存泄漏的工具。

Dalvik 运行时可能会被垃圾回收,但这并不意味着您可以忽略内存管理。您应该特别注意内存更受限制的移动设备上的内存使用情况。在本文中,我们将了解 Android SDK 中的一些内存分析工具,它们可以帮助您减少应用程序的内存使用量。

【讨论】:

    猜你喜欢
    • 2012-05-11
    • 1970-01-01
    • 2011-12-24
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 2011-12-14
    相关资源
    最近更新 更多