java - 如何修复此内存泄漏(IntentService、Runnable、ObjectBox、Repository)?
问题描述
我有一个IntentService
我每秒钟重复一次。Runnable
在Runnable
I'm requesting records fromMyItemsRepository
中,它使用ObjectBox。
某处存在内存泄漏。Android Profiler显示“Native”的巨大消耗。该方法getAllByDate()
分配了很多。
这似乎是泄漏,但我不知道如何解决它。
任何想法?提前非常感谢!
应用程序
public class App extends Application {
@Nullable
private BoxStore boxStore;
private static App instance;
public static App getApp() {
return instance;
}
public BoxStore getBoxStore() {
if (boxStore == null) {
boxStore = MyObjectBox.builder().androidContext(App.this).build();
}
return boxStore;
}
@Override
public void onCreate() {
super.onCreate();
Intent service = new Intent(this, MyService.class);
this.startService(service);
}
}
我的服务
public class MyService extends IntentService {
private final static String TAG = "MyService";
@Nullable
private Runnable runnable;
@Nullable
private List<Item> myItems;
public MyService() {
super(TAG);
myItems = new ArrayList<>();
}
@Override
public void onDestroy () {
super.onDestroy();
myItems = null; // trying to get rid off the allocation?
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
HandlerThread handlerThread = new HandlerThread(TAG + "_handlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
runnable = () -> {
try {
processMyItems();
if (runnable != null) {
handler.postDelayed(runnable, 1000); // restart
}
} catch (InterruptedException e) {
e.printStackTrace();
if (runnable != null) {
handler.postDelayed(runnable, 1000); // retry
}
} catch (Exception e) {
e.printStackTrace();
}
};
handler.postDelayed(runnable, 1000); // first run
}
protected void processMyItems() throws InterruptedException, Exception {
myItems = MyItemsRepository.getInstance().getAllByDate();
// ... do stuff with myItems ...
}
}
MyItemsRepository
public class MyItemsRepository {
private final static String TAG = "MyItemsRepository";
private static MyItemsRepository instance;
@Nullable
private Box<MyItem> box;
/**
* Singleton
* @return old or new instance
*/
public static MyItemsRepository getInstance() {
if (MyItemsRepository.instance == null) {
Logger.d(TAG, "new instance");
MyItemsRepository.instance = new MyItemsRepository();
}
return MyItemsRepository.instance;
}
public List<MyItems> getAllByDate() {
if (box == null) {
return new ArrayList<>();
}
ElapsedTimer et = new ElapsedTimer();
List<MyItem> items = box.query()
.order(MyItem_.createdAt, QueryBuilder.DESCENDING)
.build()
.find();
Logger.d(TAG, "getAllByDate() " + et.getElapsedMillisAsString());
return items;
}
}
ElapsedTimer(助手)
public class ElapsedTimer {
private long startTime;
public ElapsedTimer() {
startTime = System.currentTimeMillis();
}
public String getElapsedMillisAsString() {
return String.format("Elapsed: %s ms", getElapsedMillis());
}
}
解决方案
推荐阅读
- php - laravel 8 我想在过滤 cakephp 之前从所有控制器(如 app 控制器)访问方法。我怎么能在 laravel8 中做到这一点?
- html - 如何在两个标题之间适应并自动移动和缩放图像?
- php - 如何使用 PHP 显示我的多页项目?
- c# - 在 NetStandard 2.0 类库中托管 WCF 服务
- javascript - 在前端使用shopify admin api时出现CORS错误
- python - 使用 PyPdf multi_cell() 显示带重音符号的字符
- javascript - 在 Laravel 中按类别过滤数据
- pine-script - Pinescript 获取最低随机值的价格值
- regex - Perl:用于匹配和替换单词和可选句号的正则表达式
- excel - 一次性在所有 Excel 文件表上应用 VLookup 以及描述