在的onStop活动Android的内存管理(或关闭屏幕)内存管理、屏幕、onStop、Android

2023-09-12 05:29:34 作者:讨厌朴信惠的给爱心

我试图实现的:

在减少的活动,不再在屏幕上,即另一个活动已经启动的内存使用 的能力,这项活动仍然是导航堆栈中,所以我假设我将不得不重新建立在什么样的onStop被摧毁,在ONSTART,但不知道怎么做,当所有的意见/按钮是使用layout.xml的建立。

情况:

我有一个Android应用程序,这是非常形象沉重,但这些图片是静态的许多布局,具有相同的背景,按钮图像,导航头等等。这使我建立的布局很容易不触及code。通过在layout.xml文件中指定所有imageViews,他们的SRC属性和位置太多了。而这个伟大的工作,很容易启动和运行,但现在也有武力很多报道,由于超过了内存使用量将关闭。

等都在试图清理,并允许GC删除的图像和意见都没有在屏幕上,我读到一篇文章(的看问题底部的)的的onDestroy方法中暗示,抓一个按住布局中的根元素和递归经历树移除意见,并解除绑定它们。根据文档然而,这只是被触发的,并且不保证的时候,后退按钮是pressed。

那么的onDestroy并不能帮助我,当我推着一个新的活动入堆栈,wan't清理一下刚才离开的画面。但使用的onDestroy方法的有利的一面是,入口点开始在的onCreate,这样的观点都是正确的建立起来了。当我在的onStop使用这种方法,存储得到的清理很好当我开始一个新的活动,而是因为我已经核爆所有的意见,他们使用layout.xml建成,我不明白,我怎么还是什么需要重新打造ONSTART如果我摧毁一切的onStop特别是考虑到我从来没有创建了code的任何意见,因为他们是因为layout.xml文件的所有设置。

主要问题:如何清理内存,当我开始一个新的活动?如果上下文正确处理,是约定GC将清理一切在关闭屏幕反正和imageviews自动重新建立他们?

这个问题能以某种方式使用中的onStop?

  @覆盖
保护无效的onDestroy(){
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc()的;
}

私人无效unbindDrawables(查看视图){
    如果(view.getBackground()!= NULL){
        view.getBackground()setCallback(空)。
    }
    如果(查看的instanceof的ViewGroup){
        的for(int i = 0;我≤((ViewGroup中)查看).getChildCount();我++){
            unbindDrawables(((ViewGroup中)查看).getChildAt(一));
        }
        ((ViewGroup中)查看).removeAllViews();
    }
}
 

解决方案

A) 使用的onCreate()/的onDestroy()时,活动得到堆栈将分配和unallocate活动时,从堆栈中弹出。

B) 使用的OnStart()/的onStop()时,活动得到明显的将分配和unallocate活动时是不可见的。

Android性能优化典范 第3季

使用或者A)或B)。不要混合使用它们,否则你会分配或释放过于频繁。

在你的情况,我将一切从的onCreate()来ONSTART(),并且一切从的onDestroy()来的onStop()。

此外,还可以考虑使用this.setContentView(空)或this.setContentView(新景(本))中的onStop(),以确保老的观点可以被垃圾收集:

  @覆盖
  保护无效的onStop(){
    super.onStop();
    查看根= findViewById(R.id.RootView);
    的setContentView(新景(本))
    unbindDrawables(根);
    System.gc()的;
  }
 

What I'm trying to achieve:

Reduce memory usage of activity that is no longer on screen, ie another activity has been started The ability for this activity to still be within the navigation stack, so I'm assuming I would have to re-build what was destroyed in onStop, within onStart, but not sure how to do that when all views/buttons were built using layout.xml's .

The situation:

I have an Android app that is very image heavy, but these images are static on many of layouts, with the same backgrounds, button images, nav headers etc. This led me to build the layouts quite easily without touching code too much by specifying all the imageViews, their src attributes and positions within the layout.xml files. And this worked great, was easy to get up and running, however now there are many reports of force closes due to exceeding the memory usage.

So on in an attempt to cleanup and allow gc to remove images and views that are not on screen, I came across an article (see bottom of question) suggesting within the onDestroy method, grabbing a hold of your root element within the layout and recursively going through the tree removing views and unbinding them. However this only is fired and not guaranteed according to docs when the back buttons is pressed.

So onDestroy does not help me when I am pushing a new activity onto the stack and wan't to clean up what just left the screen. But the plus side of using the onDestroy method is that the entry point begins at onCreate, so the views are all built up correctly. When I use this method within onStop, memory get's cleaned up nicely when I start a new activity, but because I've nuked all the views, and they were built using layout.xml, I don't understand how or what I need to re-build in onStart if I destroy everything in onStop especially considering I never created any views in code as they were all setup because of the layout.xml files.

Main Questions: How do I cleanup memory when I start a new Activity? If contexts are handled correctly, is it convention that gc would cleanup all the imageviews that are off screen anyway and re-build them automatically?

Can this be used somehow within onStop ?

 @Override
protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.RootView));
    System.gc();
}

private void unbindDrawables(View view) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}

解决方案

A) Using onCreate()/onDestroy() will allocate when activity gets on the stack, and unallocate when activity is popped from the stack.

B) Using onStart()/onStop() will allocate when activity gets visible, and unallocate when activity is not visible.

Use either A) or B). Don't mix them or you'll allocate or deallocate too often.

In your case, I'd move everything from onCreate() to onStart(), and everything from onDestroy() to onStop().

Also, consider also using this.setContentView(null) or this.setContentView(new View(this)) in onStop(), to make sure the old views can be garbage collected:

  @Override
  protected void onStop() {
    super.onStop();
    View root = findViewById(R.id.RootView);
    setContentView(new View(this)) 
    unbindDrawables(root);
    System.gc();
  }