我使用Fedor的代码(https://github.com/thest1/LazyList)来加载位图.根据我的要求,我修改了几行代码.当堆内存超过阈值时,我出现内存不足错误.在同一主题上发布了各种问题.大多数人建议使用SoftReference和bitmap recycle().我正在使用SoftReference,但我仍面临问题.而且我也很困惑在哪里使用位图循环方法.
MemoryCache.java
public class MemoryCache {
private static final String TAG = "MemoryCache";
private static Map<String, SoftReference<Bitmap>> cache=Collections.synchronizedMap(
new LinkedHashMap<String, SoftReference<Bitmap>>(16,0.75f,false));//Last argument true for LRU ordering
private long size=0;//current allocated size
private long limit=30000000;//max memory in bytes
public MemoryCache(){
long cacheSize = Runtime.getRuntime().maxMemory();
setLimit(cacheSize);
}
public void setLimit(long new_limit){
limit=new_limit;
}
public Bitmap get(String id){
try{
if(!cache.containsKey(id))
return null;
//NullPointerException sometimes happen here http://code.google.com/p/osmdroid/issues/detail?id=78
return cache.get(id).get();
}catch(NullPointerException ex){
ex.printStackTrace();
return null;
}
}
public void put(String id, Bitmap bitmap){ …Run Code Online (Sandbox Code Playgroud) 我在我的活动中修改以下代码:
new Handler().postDelayed(new Runnable() {
public void run() {
txtStatus.setText("hello");
}
}, 1000);
Run Code Online (Sandbox Code Playgroud)
至:
static Runnable myRunnable = new Runnable() {
public void run() {
txtStatus.setText("hello");
};
new Handler().postDelayed(myRunnable, 1000);
Run Code Online (Sandbox Code Playgroud)
这显然不起作用,因为我们引用了一个非静态变量.
这也不起作用:
public void setText() {
txtStatus.setText("hello");
}
static Runnable myRunnable = new Runnable() {
public void run() {
setText(); // doesn't work
MyActivity.this.setText(); // still doesn't work
};
new Handler().postDelayed(myRunnable, 1000);
Run Code Online (Sandbox Code Playgroud)
那么我的初始示例如何被重写为使用静态类而不是匿名内部类(以避免内存泄漏的可能性)?
当我多次启动和退出我的应用程序时,其RAM使用量增加超过500 MB.当我检查内存转储使用adb shell dumpsys meminfo 我检查未知pss value是问题的原因.什么是大pss值的原因以及如何降低pss值.
Shared Private Heap Heap Heap
Pss Dirty Dirty Size Alloc Free
------ ------ ------ ------ ------ ------
Native 0 0 0 534460 531827 1604
Dalvik 51013 17868 50664 90480 82266 8214
Cursor 0 0 0
Ashmem 0 0 0
Other dev 14292 52 14288
.so mmap 3810 2320 1720
.jar mmap 0 0 0
.apk mmap 1305 0 0
.ttf mmap 0 0 0
.dex mmap 2960 0 …Run Code Online (Sandbox Code Playgroud) 运行我的应用程序时,我一直收到此错误。该应用程序可以正常编译,一旦我开始与它进行交互(ImageSlider),有时它会崩溃并显示该消息。
02-18 12:25:05.426: E/AndroidRuntime(4545): FATAL EXCEPTION: main
02-18 12:25:05.426: E/AndroidRuntime(4545): java.lang.OutOfMemoryError
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:493)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:299)
02-18 12:25:05.426: E/AndroidRuntime(4545): at com.oneplc.viessmannapp.imageslider.adapter.FullScreenImageAdapter.instantiateItem(FullScreenImageAdapter.java:59)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:832)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.support.v4.view.ViewPager.populate(ViewPager.java:1016)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.support.v4.view.ViewPager$3.run(ViewPager.java:244)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1761)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:1894)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1629)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957)
02-18 12:25:05.426: E/AndroidRuntime(4545): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1684)
02-18 12:25:05.426: …Run Code Online (Sandbox Code Playgroud) 我真的很高兴我将长期运行的任务切换到了协程,这些任务不断产生UI 线程的结果。与 Android 中的 AsyncTask 或常规线程相比,它提高了性能并将内存使用量减少了 3 倍,并且所有内存泄漏都消失了。
唯一的问题是,我不知道在某个时间发生异常后我应该如何重新启动长时间运行的操作......
在阅读了大量文章后,我觉得我根本不了解协程中的异常处理。让我知道如何实现所需的行为。
lateinit var initEngineJob: Job
override val coroutineContext: CoroutineContext
get() = initEngineJob + Dispatchers.Main
Run Code Online (Sandbox Code Playgroud)
fun initWorkEngineCoroutine()
{
launch {
while(true) {
val deferred = async(Dispatchers.Default) {
getResultsFromEngine()
}
val result = deferred.await()
if (result != null) {
//UI thread
draw!!.showResult(result)
}
}
}
}
fun getResultsFromEngine() :Result? {
result = // some results from native c++ engine, …Run Code Online (Sandbox Code Playgroud) 我的Android应用程序大小在设备上只有5MB,但是当我运行应用程序时,它使用了大量的内存,大约12-18 MB(以及更多的ics设备).我试图找到一个解释,为什么我的应用程序使用大量的RAM,我也使用解析推送服务.我的应用程序是图像密集型,可能是一个可能的原因.如何减少应用程序的RAM消耗.
我为我的按钮设置了监听器:
View onCreateView(...) {
...
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//some work
}
});
...
}
Run Code Online (Sandbox Code Playgroud)
如果我使用ButterKnife,建议打电话给ButterKnife.unbind(this)在onDestroyView(){..}.我是否需要删除侦听器以避免内存泄漏?
void onDestroyView() {
...
btn.setOnClickListener(null)
}
Run Code Online (Sandbox Code Playgroud) android android-lifecycle android-fragments android-memory butterknife
所以,我经常听到"坚持静态活动或视图,特别是在长时间运行的AsyncTask中会导致内存泄漏并导致应用程序崩溃".
但是,我无法在Android模拟器中真正证明这一点.
我究竟做错了什么?
public class MainActivity extends AppCompatActivity {
static TextView label;
static List<Activity> sHolder = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroup vg = findViewById(R.id.blah);
for (int i=0; i<1000000; i++) {
ImageView im = new ImageView(this);
im.setImageDrawable(getApplicationContext().getDrawable(R.drawable.kitten_original));
vg.addView(im);
new MyTask(this).execute();
}
sHolder.add(this);
}
@Override
protected void onStart() {
super.onStart();
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
class MyTask extends AsyncTask<Void, Void, Void> {
Activity activity;
public MyTask(Activity …Run Code Online (Sandbox Code Playgroud) 我决定调查我的应用程序的内存使用情况,我查看了Android Studio的内存监视器,我的内存使用量大约是68 MB.对我来说这看起来太高了.
我打开了内存分配器,并从应用程序的开头开始跟踪.我看到有一个49 MB的a分配NonMovableArray,这是一个Bitmap.
我调试了应用程序,发现它是我使用的背景.下面的行来自PhoneWindow.java文件,这是Android将背景分配给我认为的屏幕的地方.背景对象的大小为49 MB,分辨率为2625x4669.
我的应用程序没有透支,我有一个应用于整个主题的背景.
我drawable在JPG格式的文件夹中有一个背景可绘制,分辨率为750x1,334.
PhoneWindow.java
if (mBackgroundResource != 0) {
background = getContext().getDrawable(mBackgroundResource);
} else {
background = mBackgroundDrawable;
}
Run Code Online (Sandbox Code Playgroud)
我正在摩托罗拉Nexus 6设备上进行测试,该设备具有560密度,分辨率为1440 x 2560.
有两点我不明白.
如果你们可以向我解释这将是伟大的.谢谢!
我不断收到有关我的静态片段实例的内存泄漏的警告。我声明如下:
私有静态myFragment thisFragment;
并在这里调用:
public static myFragment newInstance() {
if (thisFragment == null) {
thisFragment = new myFragment();
}
return thisFragment;
}
Run Code Online (Sandbox Code Playgroud)
我该如何解决?有任何想法吗?
谢谢!
android memory-leaks android-context android-fragments android-memory
android ×10
android-memory ×10
java ×2
memory-leaks ×2
performance ×2
butterknife ×1
kotlin ×1