android - BiometricPrompt:BiometricFragment 和 Activity 内存泄漏
问题描述
您好,我发现了 2 个我想解决的内存泄漏。
收到回调后onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result)
,我想setResult()
调用finish()
ActivityB 回到 ActivityA。
尽管这确实可以正常工作,但在调用finish()
.
以下是重现内存泄漏(ActivityB)的相关代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);;
BiometricPrompt biometricPrompt = biometricPromptInstance();
biometricPrompt.authenticate(buildPromptInfo());
}
private BiometricPrompt biometricPromptInstance(){
Executor executor = ContextCompat.getMainExecutor(this);;
BiometricPrompt.AuthenticationCallback callback = new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
setResult(RESULT_OK);
//Causing leak: ////////////////////////////////////////////////
finish();
/////////////////////////////////////////////////////////////////
}
@Override
public void onAuthenticationFailed() {
}
};
return new BiometricPrompt(this, executor, callback);
}
private BiometricPrompt.PromptInfo buildPromptInfo(){
return new BiometricPrompt.PromptInfo.Builder()
.setTitle("Login")
.setSubtitle("Log in using your biometric credential")
.setNegativeButtonText("Cancel")
.build();
}
解决方案
问题在于执行器的初始化,
// initialize biometric executor
executor = ContextCompat.getMainExecutor(this)
更新到
// initialize biometric executor
executor = ContextCompat.getMainExecutor(applicationContext)
在内部,Google 使用 Handler 在新线程中执行操作。上下文关联不应该是您的活动(或片段)。
/**
* Return an {@link Executor} that will run enqueued tasks on the main
* thread associated with this context. This is the thread used to dispatch
* calls to application components (activities, services, etc).
*/
public static Executor getMainExecutor(Context context) {
if (Build.VERSION.SDK_INT >= 28) {
return context.getMainExecutor();
}
return new MainHandlerExecutor(new Handler(context.getMainLooper()));
}
private static class MainHandlerExecutor implements Executor {
private final Handler mHandler;
MainHandlerExecutor(@NonNull Handler handler) {
mHandler = handler;
}
@Override
public void execute(Runnable command) {
if (!mHandler.post(command)) {
throw new RejectedExecutionException(mHandler + " is shutting down");
}
}
}
推荐阅读
- html - 我可以在背景图像上制作一个空白页吗?
- r - 将列作为函数参数传递
- python - Flask 有很多通过模型关联
- nginx - Nginx“large_client_header_buffers”指令的最大大小的含义
- python - 是否可以在不使用字典理解的情况下将字典的值与 int 进行比较?
- c++ - 为什么你想要一个类中的结构?
- c# - .NET Core 基础 - 构造函数注入行为
- mongodb - 即使有索引,MongoDB 也发现查询非常慢
- javascript - react.js 与 apollo 查询 graphql - 错误:对象作为 React 子项无效
- hibernate-validator - Hibernate-validator 6:@Max 注释的奇怪行为,在 Number 字段上设置了 BigDecimal