1

首先从我的项目体系结构开始,我使用MVP和Dagger 2进行依赖注入。使用范围匕首避免活动泄漏2

我一直在探索范围匕首,我的问题是更好地理解活动范围内的范围。

尽管使用活动范围,但我有一个活动(视图)通过演示者泄漏。

由于我是匕首的新手,我觉得我失去了一些东西。

我假设范围应该处理我的视图为null当活动被破坏(虽然现在不知道它将如何)。是我的假设是正确的?如果是的话我做错了什么,否则是否有可能避免使用匕首查看泄漏?我知道detachView的方法,只是好奇,如果我们可以用匕首2实现同样的事情。

P.S:我通过leakCanary了解了泄漏。

以下是我的代码

LoginActivity.class

public class LoginActivity extends BaseActivity implements LoginContract.View { 


    private static final String TAG = "LoginActivity"; 
    @Inject 
    LoginPresenter presenter; 

    private LoginComponent loginComponent; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_login); 
    createComponent(); 
    initViews(); 
    } 

    private void createComponent() { 
    loginComponent = ((MyApplication) getApplication()).getRepositoryComponent() 
      .COMPONENT(new LoginPresenterModule(this)); 
    loginComponent.inject(this); 
} 

@Override 
protected void onDestroy() { 
    super.onDestroy(); 
    loginComponent = null; 
} 

LoginPresenterModule.class

@Module 
public class LoginPresenterModule { 

private final LoginContract.View view; 

public LoginPresenterModule(LoginContract.View view) { 
    this.view = view; 
} 


@Provides 
@ActivityScoped 
public LoginContract.View providesView(){ 
    return view; 
} 
} 

LoginComponent.class

@ActivityScoped 
@Subcomponent(modules = LoginPresenterModule.class) 
public interface LoginComponent { 

    void inject(LoginActivity loginActivity); 
} 

LoginPresenter.cla SS

@ActivityScoped 
public class LoginPresenter implements LoginContract.Presenter { 

private static final String TAG = "LoginPresenter"; 
private LoginContract.View view; 

private DataRespository dataRespository; 

@Inject 
LoginPresenter(LoginContract.View view, DataRespository dataRespository) { 
    this.view = view; 
    this.dataRespository = dataRespository; 
} 


@Override 
public void initTest(String testNo) { 

    view.showProgressIndicator(); 
    dataRespository.sendTest(testNo, new DataSource.onResponseCallback<Void>() { 
     @Override 
     public void onSuccess(Void obj) { 
      Log.d(TAG, "onSuccess: "); 

     } 

     @Override 
     public void onError(@NotNull ErrorWrapper error) { 
      Log.d(TAG, "onError: "); 
     } 
    }); 

} 

@Override 
public void start() { 

} 

}

DataRespositoryComponent.class

@ApplicationScoped 
@Component(dependencies = ApplicationComponent.class,modules = 
DataRespositoryModule.class) 
public interface DataRepositoryComponent { 

LoginComponent COMPONENT(LoginPresenterModule loginPresenterModule); 
} 

基本上,同时使网络呼叫视图被泄漏。 我的漏斗堆栈: enter image description here

+0

你可以包括来自泄漏金丝雀的痕迹/信息,从哪里泄漏? –

+0

只是。检查出它 –

回答

3

此活动泄漏与Dagger无关,Dagger也无法帮助阻止它。

问题出在dataRespository.sendTest(..anonymousCallback..)您添加回调来接收结果。

匿名类以及非静态内部类将保持对其封闭对象的引用。在你的情况下,回调会保持对主持人的引用,主持人保持对视图的引用,该引用保持对活动的引用(这是LeakCanary显示的内容)。

由于回调处于活动状态,直到它收到响应或错误,如果您的活动在回调完成之前被销毁,它将会泄漏。


要解决您的问题,您需要停止或取消注册您的回调,或删除对活动的引用。在这种情况下,当活动被破坏以防止活动泄漏时,在您的演示者中设置view = null可能就足够了。

只要确保在回调中访问它之前检查视图是否为空。

+0

视图对象不应该活动,因为它是活动作用域?还是像匕首不负责杀死对象? –

+0

@farhanpatel匕首只创建对象。垃圾收集器不会收集它,因为okHttp仍然引用它 –

+0

谢谢,现在你已经解释了它似乎很明显! :D –