3

I have the few Base classes defined for my Activity and Fragment, Presenter, and ViewHolder, and ViewModel, and an interface and Presenter being defined, All other activities inheriting these base classes, and In my BaseActivity class and BaseFragmentClass, i am creating lifecycleRegistry object and initializing it, but when the App is launched it crashes with error getLifecycle() returned null in ComponentActivity's constructor. Please make sure you are lazily constructing your Lifecycle in the first call to getLifecycle() rather than relying on field initialization.

File: BaseFragment.java

package com.example.myapp.data.helper.base;


import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleRegistry;
import androidx.lifecycle.ViewModelProviders;

public abstract class BaseFragment<V extends MvpView, P extends BasePresenter<V>>
        extends Fragment implements MvpView, View.OnClickListener {
    private  final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
    protected P presenter;
    private int defaultValue = -1;
    private ViewDataBinding viewDataBinding;
    private View rootView;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    @SuppressWarnings("unchecked")
    @CallSuper
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        BaseViewModel<V, P> viewModel = ViewModelProviders.of(this).get(BaseViewModel.class);
        boolean isPresenterCreated = false;
        if (viewModel.getPresenter() == null) {
            viewModel.setPresenter(initPresenter());
            isPresenterCreated = true;
        }
        presenter = viewModel.getPresenter();
        presenter.attachLifecycle(getLifecycle());
        presenter.attachView((V) this);
        if (isPresenterCreated)
            presenter.onPresenterCreated();
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        startUI();
    }

    @Override
    public void onClick(View view) {

    }

    @NonNull
    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }

    protected abstract void startUI();

    protected abstract void stopUI();

    protected ViewDataBinding getViewDataBinding() {
        return viewDataBinding;
    }

    @CallSuper
    @Override
    public void onDestroyView() {
        super.onDestroyView();

        if (presenter != null) {
            presenter.detachLifecycle(getLifecycle());
            presenter.detachView();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (presenter != null) {
            presenter.detachLifecycle(getLifecycle());
            presenter.detachView();
        }

        stopUI();
    }

    private BaseActivity<V,P> getBaseActivity() {
        return ((BaseActivity<V,P>) getActivity());
    }

    private boolean isBaseActivityInstance() {
        return getActivity() instanceof BaseActivity;
    }

    protected void setTitle(String title) {
        if (isBaseActivityInstance()) {
            getBaseActivity().setTitle(title);
        }
    }

    protected void setClickListener(View... views) {
        for (View view : views) {
            view.setOnClickListener(this);
        }
    }

    protected abstract P initPresenter();
}

File: BaseActivity.java

package com.example.data.helper.base;

import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.lifecycle.ViewModelProviders;

public abstract class BaseActivity<V extends MvpView, P extends BasePresenter<V>>
        extends AppCompatActivity implements MvpView, View.OnClickListener, LifecycleOwner {


    private final LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this) ;
    protected P presenter;
    private ViewDataBinding viewDataBinding;
    private Menu menu;
    private int defaultValue = -1;

    @NonNull
    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        int layoutId = getLayoutId();
        if (layoutId > defaultValue) {

            try {
                viewDataBinding = DataBindingUtil.setContentView(this, layoutId);
            } catch (Exception e) {
                if (viewDataBinding == null) {
                    setContentView(layoutId);
                }
            }

            BaseViewModel<V,P> viewModel = ViewModelProviders.of(this).get(BaseViewModel.class);
            boolean isPresenterCreated = false;

            if (viewModel.getPresenter() == null) {
                viewModel.setPresenter(initPresenter());
                isPresenterCreated = true;
            }

            presenter = viewModel.getPresenter();
            presenter.attachLifecycle(getLifecycle());
            presenter.attachView((V) this);
            if (isPresenterCreated) {
                presenter.onPresenterCreated();
            }
        }

        startUI();
    }

    @Override
    protected void onResume() {
        super.onResume();
        onResumeUI();
    }
    protected abstract void onResumeUI();
    */

    protected abstract void startUI();

    protected abstract void stopUI();

    protected ViewDataBinding getViewDataBinding() {
        return viewDataBinding;
    }

    protected static void runCurrentActivity(Context context, Intent intent) {
        context.startActivity(intent);
    }

    @Override
    public void onClick(View view) {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.stopUI();
        presenter.detachLifecycle(getLifecycle());
        presenter.detachView();
    }

    protected abstract P initPresenter();

    protected void setTitle(String title) {
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setTitle(title);
        }
    }

    protected void setClickListener(View... views) {
        for (View view : views) {
            view.setOnClickListener(this);
        }
    }

    protected BaseFragment<?, ?> mBaseCurrentFragment;

    protected void commitFragment(int parentId, BaseFragment<?, ?> baseFragment) {
        getSupportFragmentManager()
                .beginTransaction()
                .replace(parentId, baseFragment, baseFragment.getClass().getName())
                .commit();

        setCurrentFragment(baseFragment);
    }

    protected void setCurrentFragment(BaseFragment<?, ?> baseFragment) {
        this.mBaseCurrentFragment = baseFragment;
    }

    protected BaseFragment<?, ?> getBaseCurrentFragment() {
        return mBaseCurrentFragment;
    }
}

**File: MvpView

public interface MvpView{

}

File : BasePresenter.java

public abstract class BasePresenter<V extends MvpView> implements LifecycleObserver, Presenter<V> {

    private V myMvpView;
    private Bundle stateBundle;

    @Override
    public void attachView(V mvpView) {
        myMvpView = mvpView;
    }

    @Override
    public void detachView() {
        mMvpView = null;
    }

    @Override
    public void attachLifecycle(Lifecycle lifecycle) {
        if (lifecycle != null) {
            lifecycle.addObserver(this);
        }
    }

    @Override
    public void detachLifecycle(Lifecycle lifecycle) {
        if (lifecycle != null) {
            lifecycle.removeObserver(this);
        }
    }

    public boolean isViewAttached() {
        return myMvpView != null;
    }

    public V getMvpView() {
        return myMvpView;
    }

    public Bundle getStateBundle() {
        return stateBundle == null ?
                stateBundle = new Bundle() : stateBundle;
    }

    public void checkViewAttached() {
        if (!isViewAttached()) throw new MvpViewNotAttachedException();
    }

    public static class MvpViewNotAttachedException extends RuntimeException {
        public MvpViewNotAttachedException() {
            super("Please call Presenter.attachView(MvpView) before" +
                    " requesting data to the Presenter");
        }
    }

    @Override
    public void onPresenterDestroy() {
        if (stateBundle != null && !stateBundle.isEmpty()) {
            stateBundle.clear();
        }
    }
}

Updates: I try to update the code of BaseActivity.java and BaseFragment.java by making lifeCycleRegistry as Non Final. and initializing it in getLifecycle if it is null , but then i can only see a blank screen, Not sure Why?

public abstract class BaseActivity<V extends MvpView, P extends BasePresenter<V>>
        extends AppCompatActivity implements MvpView, View.OnClickListener {
      private LifecycleRegistry = new LifeCycleRegistry(this);

    @NonNull
    @Override
    public LifecycleRegistry getLifecycle() {
        if (lifecycleRegistry==null){

            lifecycleRegistry= new LifecycleRegistry(this);
        }
        return lifecycleRegistry;
    }

}

All other code is same.

Gaurav
  • 533
  • 5
  • 20
  • Why are you even providing your own `LifecycleRegistry` or overriding `getLifecycle()`? – ianhanniballake Jul 17 '20 at 17:40
  • I was actually refactoring a source code of someone else written app, The old coder has written the way like this, i am also not able to understand why he needs to have its own lifecycleregistry – Gaurav Jul 17 '20 at 18:02

1 Answers1

5

Remove the override to getLifecycle() and your own LifecycleRegistry. This was neccessary before Architecture Components became stable and directly integrated into AppCompatActivity and Fragment, but is not necessary anymore.

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • 1
    It works , basically i need to migrate the app to androidx and then possibly switch the architecture to MVVM i guess it is not going to be simple. – Gaurav Jul 17 '20 at 18:13
  • Any version of Support Library 26.1.0 or higher would work since those was that version that implemented `LifecycleOwner` for you as per [the release notes](https://developer.android.com/jetpack/androidx/releases/archive/arch#100_alpha_9-1_-_september_13_2017). – ianhanniballake Jul 17 '20 at 18:15
  • Oh okay , though the screen still i got is blank, it is connecting to some remote service i guess it is failing due to which screen is blank, i will debug this thanks for the help. – Gaurav Jul 17 '20 at 18:19
  • Does this also same for CustomViews . Please answer my question too. https://stackoverflow.com/questions/76514016/lifecycleowner-migration-in-customview-android – Taimoor Khan Jun 21 '23 at 08:00