Search code examples
javaandroidandroid-fragmentsrealmrealm-java

Realm in Fragment causing NullPointerException


I'm confused as to how to handle Realm in fragments when the fragment's activity extends a base activity that controls Realm.

In other words, I have this structure:

Base Activity -> User Activity -> Base Fragment -> Fragment

Everything works fine, until I exit the activity (i.e. go back to the previous activity). I get this error:

java.lang.RuntimeException: Unable to destroy activity {UserActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void io.realm.Realm.close()' on a null object reference

...

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void io.realm.Realm.close()' on a null object reference at BaseFragment.onDestroyView

My base Activity:

public abstract class BaseActivity extends AppCompatActivity {
    private Realm realm;

    protected abstract int getLayoutResource();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getLayoutResource());

        realm = Realm.getDefaultInstance();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        realm.close();
    }

    public Realm getRealm() {
        return realm;
    }
}

My main Activity (where the Fragments are created):

public class UserActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String type = getIntent().getStringExtra("type");

        Fragment fragment = null;
        if (findViewById(R.id.fragment_container) != null) {
            if (savedInstanceState != null) {
                return;
            }

            if (type.equals("first")) {
                fragment = new FirstFragment();
            } else if (type.equals("second")) {
                fragment = new SecondFragment();
            }

            getSupportFragmentManager().beginTransaction()
                    .add(R.id.fragment_container, fragment).commit();
        }
    }

    @Override
    protected int getLayoutResource() {
        return R.layout.activity_user;
    }
}

And all of my Fragments extend a base Fragment. Here is my base Fragment:

public abstract class BaseFragment extends Fragment {

    private Realm realm;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        realm = Realm.getDefaultInstance();

        return inflater.inflate(getFragmentLayout(), container, false);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        realm.close();
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        realm.executeTransaction(new Realm.Transaction() {
            @Override
                public void execute(Realm realm) {
                    // some realm operation
                }
        });
    }

    protected abstract int getFragmentLayout();
}

What's causing the problem? Am I managing Realm improperly?


Solution

  • Get rid of the realm.close(); in your BaseFragment that is going to be closed when you destroy the activity, so you are going to be closing it twice, which is why you get the NPE. So if you remove the realm.close(); in your Fragment, and let the Activity handle closing Realm.