我在我的代码中收到警告:
这个AsyncTask类应该是静态的,否则可能会发生泄漏(匿名android.os.AsyncTask)
完整的警告是:
此AsyncTask类应该是静态的,否则可能会发生泄漏(匿名android.os.AsyncTask)静态字段将泄漏上下文.非静态内部类具有对其外部类的隐式引用.如果该外部类例如是片段或活动,则此引用意味着长时间运行的处理程序/加载器/任务将保留对活动的引用,从而阻止其收集垃圾.同样,对来自这些较长时间运行的实例的活动和片段的直接字段引用可能会导致泄漏.ViewModel类绝不应指向视图或非应用程序上下文.
这是我的代码:
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... params) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.notifyDataSetChanged();
}
});
return null;
}
}.execute();
Run Code Online (Sandbox Code Playgroud)
我该如何纠正?
通常我会遇到一个给定对象需要有很多监听器的情况.例如,我可能有
class Elephant {
public void addListener( ElephantListener listener ) { ... }
}
Run Code Online (Sandbox Code Playgroud)
但我会遇到很多这样的情况.也就是说,我也会有一个Tiger对象TigerListener.现在,TigerListeners和ElephantListeners完全不同:
interface TigerListener {
void listenForGrowl( Growl qrowl );
void listenForMeow( Meow meow );
}
Run Code Online (Sandbox Code Playgroud)
而
interface ElephantListener {
void listenForStomp( String location, double intensity );
}
Run Code Online (Sandbox Code Playgroud)
我发现我总是必须在每个动物类中继续重新实现广播机制,并且实现总是相同的.有首选模式吗?
阅读完这篇文章后,我开始考虑与Volley的内存泄漏.通常,使用Volley实现的侦听器具有对外部类(活动)的隐式或显式引用.例如:
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
updateLayout();
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下有一个隐式引用...或者我可能想创建一个自定义JsonObjectRequest来内化响应处理,并需要在其构造函数中传入对调用活动的引用.
现在让我说我开始一个Web请求,但在响应回来之前,我离开了启动请求的活动.根据我的理解,JsonObjectRequest对象将保留对我的活动的引用并防止它被垃圾收集.
- 我正确理解这一点,这是一种合理的恐惧吗?
- Volley库会自动处理这个吗?
- 如果我正在创建一个自定义的JsonObjectRequest并传入一个"this"(对活动的引用),我是否需要为该活动创建一个WeakReference?
当我更改为横向模式时,使用全屏位图创建的对象很少.
当我滚动另一个对象被调用并且它的位图被显示时,当我反复这样做,位图大小超过vm预算错误时,我已经做了所有的事情,比如recycle()设置null然后调用GC(),我仍然有同样的错误.创建位图....
bitmap = Bitmap.createBitmap(ChartProperties.getChartWidth(),
ChartProperties.getChartHeight(),
Bitmap.Config.RGB_565);
imageCache.put(String.valueOf(LandscapeChartActivity.getActiveFeature()),
new SoftReference(bitmap));
if(imageCache != null){
for (int i = 0; i < imageCache.size(); i++) {
if (imageCache.get(String.valueOf(i)) != null) {
imageCache.get(String.valueOf(i)).get().recycle();
imageCache.put(String.valueOf(i), null);
}
}
Runtime.getRuntime().gc();
imageCache.clear();
imageCache = null;
Run Code Online (Sandbox Code Playgroud) 我有以下方法,它有一个 ImageSwitcher,用户可以左右滑动。所选图像显示在屏幕中央。我已经在低内存手机上对高分辨率图像进行了一些图像缩放,但是当从左到右快速滑动时,我仍然遇到 Bitmap OutOfMemoryEexception。我想改变这条线mSwitcher.setImageURI(myUri);(这是导致 OOME 的行)转换为使用弱引用,以便它可以自动进行垃圾收集。我怎样才能做到这一点?这是性能优化此方法的最佳方法吗?
谢谢
方法:
public void onItemSelected(AdapterView parent, View v, int position, long id) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyAppName");
File[] cachedOnSDImages = mediaStorageDir.listFiles();
countArray = new Integer[cachedOnSDImages.length];
fileArray = new String[cachedOnSDImages.length];
fileArray[position] = cachedOnSDImages[position].getAbsolutePath();
Uri myUri = Uri.parse(fileArray[position]);
mSwitcher.setImageURI(myUri); // weakly reference myUri in this line
this.currentpos = position;
}
Run Code Online (Sandbox Code Playgroud)
我应该在这里添加 mSwitcher 实例化:
private void makeSwitcher() {
mSwitcher = (ImageSwitcher) findViewById(R.id.switcher);
mSwitcher.setFactory(this);
mSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_in));
mSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
android.R.anim.fade_out));
}
Run Code Online (Sandbox Code Playgroud) 我在我的(Obj_A)中使用WeakReference for ImageView,并将此ImageView WeakReference传递给另一个将其分配给ImageView变量的对象(Obj_B)(但也不是WeakReference),因此接收器ImageView变量将具有WeakReference的本质?
我希望我能够正确地塑造我的问题,我希望你理解我的意思.
我知道在这篇文章中已经回答了一个类似的问题。但是,我仍然对 java 是否有保留循环问题感到困惑,因为 java 也有 WeakReference 类。那么,它们的目的是否相同?他们两个有什么区别?