代码之家  ›  专栏  ›  技术社区  ›  Ritesh Shakya

使用Dagger2和setRetainInstance时获得NullPointException(true);

  •  1
  • Ritesh Shakya  · 技术社区  · 6 年前

    所以我跟着 Clean Architecture 来设计我的应用程序。我有一个 Activity 带有一个视图寻呼机,该寻呼机有两个 Fragment 在它里面。我正在注射 PagerAdapter 通过匕首。

    我理解你的要求 setRetainInstance(true) 在碎片上防止其被破坏 getActivity() 如果活动被破坏,则在该片段上可能返回问题。当我的活动在后台并且(可能)已被销毁后尝试恢复时,我遇到了一个NullPointException。

    所以我的问题是

    • 有没有更好的方法来完成我想做的事情?
    • 有人能给我指点什么资源吗?
    • 还不确定如果片段已被破坏,为什么片段和适配器仍处于活动状态。我没有得到漏金丝雀内存泄漏。

    我的活动有一个Dagger组件MainActivityComponent,注入方式如下。并扩展了HasComponent。有关这方面的更多信息,请参阅 HasComponent

    主要活动。Java语言

    DaggerMainActivityComponent.builder()
     .applicationComponent(getApplicationComponent())
     .activityModule(getActivityModule())
     // Module for each fragment
     .conversationListModule(new ConversationListModule(this)) 
     .friendsListModule(new FriendsListModule(this))
     .build()
     .inject(this);
    

    获取活动的组件

    // Cause of the NullPointException getActivity()
    protected <C> C getComponent(Class<C> componentType) {
        return componentType.cast(((HasComponent<C>) getActivity()).getComponent());
    } 
    

    如果你们有任何困惑,请告诉我。我知道我的解释一团糟。谢谢

    使现代化

    即使我移除 setRetainInstance(true) 无法防止此错误。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Ritesh Shakya    6 年前

    问题

    当应用程序在后台停留一段时间,并且安卓回收了最近显示的活动时,就会出现问题。带回应用程序会导致NullPointerException(NPE),因为activitys组件在初始化之前由片段调用(片段和活动都是同时重新创建的)。

    解决方案

    在BaseFragment类中引入了两种生命周期方法。

    1. onInjectView() 调用以在onCreate(Bundle)上执行可选注入,如果抛出异常或返回false,则再次在onActivityCreated(Bundle)上调用该异常。在这种方法中,您可以获得注入组件并注入视图。Retrun true如果注射成功,则不会再次调用。
    2. 根据返回的值,调用第二个方法。方法名为 ,因为它仅在片段已注入且注入的字段可以初始化时调用。

    碱基片段

    public abstract class BaseFragment extends Fragment {
    
        private boolean mIsInjected = false;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
    
            try {
                mIsInjected = onInjectView();
            } catch (IllegalStateException e) {
                Log.e(e.getClass().getSimpleName(), e.getMessage());
                mIsInjected = false;
            }
        }
    
        @Override
        public void onViewCreated(View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            if (mIsInjected) onViewInjected(savedInstanceState);
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            if (!mIsInjected) {
                mIsInjected = onInjectView();
                if (mIsInjected) onViewInjected(savedInstanceState);
            }
        }
    
        @SuppressWarnings("unchecked")
        protected <C> C getComponent(Class<C> componentType) throws IllegalStateException {
            C component = componentType.cast(((HasComponent<C>) getActivity()).getComponent());
            if (component == null) {
                throw new IllegalStateException(componentType.getSimpleName() + " has not been initialized yet.");
            }
            return component;
        }
    
    
        protected boolean onInjectView() throws IllegalStateException {
            // Return false by default.
            return false;
        }
    
        @CallSuper
        protected void onViewInjected(Bundle savedInstanceState) {
            // Intentionally left empty.
        }
     }
    

    用法

    public class SampleFragment extends BaseFragment implements SampleView {
    
        @Inject
        SamplePresenter mSamplePresenter;
    
        @Override
        protected boolean onInjectView() throws IllegalStateException {
            getComponent(SampleComponent.class).inject(this);
            return true;
        }
    
        @Override
        protected void onViewInjected(Bundle savedInstanceState) {
            super.onViewInjected(savedInstanceState);
            this.mSamplePresenter.setView(this);
        }
    }
    

    更多信息请访问 Efficient and bug-free fragment injection in Android MVP applications