使用Fragment中Application-component中初始化的类

时间:2015-03-12 09:48:53

标签: android android-fragments

以下问题:

在我的Android-App中,我使用Application-Component来实例化一个名为AppController的类。该类用于实例化其他所谓的" Manager" -classes。 例如,DatabaseManager用于访问SQLite数据库。

在我的活动中,我在" onCreate"方法:

mApplication = (MyApplication) getApplication();
mAppController = mApplication.getAppController();

现在,当我创建一个需要访问此AppController的片段时,因为片段的视图需要来自DatabaseManager的一些信息。

目前我使用以下方法:

从父活动中获取AppController onAttach(Activity activity),然后在片段mAppController.getDatabaseManager()中使用onCreateViev(...)

此刻这似乎有效。但我已经读过onAttach(...)中的activity-Object有时可能是null

这就是问题:

null中的活动为onAttach时,我将无法获得DatabaseManager,并且在设置视图时我的应用程序会崩溃。

目前我讨厌的解决方案

目前,我唯一能想到的是检查onAttach(...)中的活动是否为空,如果为空,则创建不在onCreateView(...)但在onActivityCreated(...)中的布局视图生命周期方法,因为它将100%确定活动不再是null

我不喜欢这种方法是我会创建片段的视图,而不是在"正确"生命周期方法,我不确定这是否有任何副作用...

我感谢每一个意见和评论:)

Siggy

3 个答案:

答案 0 :(得分:1)

就我个人而言,我正在为此使用静态变量。

public class CustomApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationHolder.INSTANCE.setCustomApplication(this);
    }
}

然后我可以将变量放在单例枚举模式中:

public enum ApplicationHolder {
    INSTANCE;

    private CustomApplication customApplication = null;

    public CustomApplication getCustomApplication() {
        return customApplication;
    }

    public void setCustomApplication(CustomApplication customApplication) {
        this.customApplication = customApplication;
    }
}

通过这种方式,您始终可以通过

访问应用程序
ApplicationHolder.INSTANCE.getCustomApplication();

然而,如果您不需要使用ProGuard 进行混淆,可以将其提升一个档次(因为Dagger 1.2.2无法正常工作)与ProGuard :( ...)

因为那时您可以使用@Provides方法创建一个返回此应用程序的模块

@Module(complete = false, library = true)
public class ContextModule {
    @Provides
    public CustomApplication providesApplication() {
        return ApplicationHolder.INSTANCE.getCustomApplication();
    }
}

因为这样,您可以在自己的模块中为@Provides创建AppController方法

@Module(complete = false, library = true)
public class AppControllerModule {
    @Provides
    @Singleton
    public AppController providesAppController(CustomApplication customApplication) {
        return new AppController(customApplication);
    }
}

因此,AppController需要一个构造函数,它使CustomApplication参数初始化自己。

为了完成这项工作,您需要使用Dagger之类的

//CustomApplication
@Override
public void onCreate() {
    super.onCreate();
    ApplicationHolder.INSTANCE.setCustomApplication(this);
    Injector.INSTANCE.init(new RootModule());
}

RootModule的位置

@Module(
    includes = {
        ApplicationModule.class,
        AppControllerModule.class
    },
    injects = {
        YourFragment.class
    }
)
public class RootModule {
}

Injector

public enum Injector
{
    INSTANCE;

    private ObjectGraph objectGraph = null;

    public void init(final Object rootModule)
    {

        if(objectGraph == null)
        {
            objectGraph = ObjectGraph.create(rootModule);
        }
        else
        {
            objectGraph = objectGraph.plus(rootModule);
        }

        // Inject statics
        objectGraph.injectStatics();

    }

    public void init(final Object rootModule, final Object target)
    {
        init(rootModule);
        inject(target);
    }

    public void inject(final Object target)
    {
        objectGraph.inject(target);
    }

    public <T> T resolve(Class<T> type)
    {
        return objectGraph.get(type);
    }
}

然后你可以做

public class YourFragment extends Fragment {
    ...
    @Inject
    AppController appController;

    @Override
    protected void onActivityCreated(Bundle bundle) {
         super.onActivityCreated(bundle);
         Injector.INSTANCE.inject(this);
    }
}

有关Dagger的更多信息,请访问:https://stackoverflow.com/a/27036934/2413303

虽然我认为onCreateView也适用于Injector

答案 1 :(得分:0)

为什么不在[{1}}中获取DatabaseManager的参考资料?

答案 2 :(得分:0)

首先,你应该在onCreate()方法中创建你的视图,并在活动(以及你需要的所有东西)变得可用时用数据填充它。 此外,您可以尝试避免在Fragment中处理数据。您可以定义用于加载必要数据的界面,使您的活动实现它,并在用户执行操作时要求活动完成所有工作。你的片段只需要显示它的结果。