My app crashes when RealmList is null. It was working fine, until i changed my emulator from API 23 to API 19.
I already did a check but its not, but still getting crashes. I tried doing this
RealmChangeListener realmChangeListener = new RealmChangeListener() {
@Override
public void onChange(Object element) {
if(getPostsFromDb() != null){
mAdapter.swapData(getPostsFromDb());
}
}
};
The App still crash with NPE
How can i resolve this?
public class CartFragment extends Fragment{
private Realm realm;
private RecyclerView mRecyclerView;
private BucketFragmentAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private ProgressBar circularProgessBar;
private RelativeLayout emptyView;
RealmChangeListener realmChangeListener = new RealmChangeListener() {
@Override
public void onChange(Object element) {
mAdapter.swapData(getPostsFromDb());
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
realm = Realm.getDefaultInstance();
int user_id = Utils.getStoredUser(getActivity()).getId();
BucketListAPIHelper.loadBucket(user_id);
realm.addChangeListener(realmChangeListener);
}
public View onCreateView(LayoutInflater inflater, ViewGroup vg,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.cart_fragment, vg, false);
emptyView = (RelativeLayout) view.findViewById(R.id.empty_view);
circularProgessBar = (ProgressBar) view.findViewById(R.id.circular_progress_bar);
circularProgessBar.setVisibility(View.VISIBLE);
if(isNetworkConnected()){
circularProgessBar.setVisibility(View.GONE);
}else{
new AlertDialog.Builder(getActivity())
.setTitle("No Internet Connection")
.setMessage("It looks like your a problem with your internet connection. Please turn it " +
"on and try again")
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}).setIcon(android.R.drawable.ic_dialog_alert).show();
}
loadBucket(view);
return view;
}
private void loadBucket(View view) {
RealmResults<Bucket> realmResults = getPostsFromDb();
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
if(!realmResults.isEmpty()){
mRecyclerView.setVisibility(View.VISIBLE);
emptyView.setVisibility(View.GONE);
circularProgessBar.setVisibility(View.GONE);
mAdapter = new BucketFragmentAdapter(realmResults, getActivity(), true);
mRecyclerView.setAdapter(mAdapter);
}else{
mRecyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
}
}
@Subscribe
public void onPostSuccess(BucketListAPIHelper.PostsInfoSuccess postInfo) {
//setRefreshing(false);
}
public RealmResults<Bucket> getPostsFromDb() {
RealmResults<Bucket> realmResults = realm.where(Bucket.class).findAll();
if(realmResults != null){
return realmResults;
}
return realmResults;
}
/* Present user with some error message when there's an issue while retrieving data */
@Subscribe
public void onPostFailure(BucketListAPIHelper.PostsInfoFailure error) {
///setRefreshing(false);
//displaySimpleConfirmSnackBar(recyclerView, error.getErrorMessage());
}
private boolean isNetworkConnected() {
ConnectivityManager connMgr = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); // 1
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); // 2
return networkInfo != null && networkInfo.isConnected(); // 3
}
@Override
public void onPause() {
super.onPause();
EventBusSingleton.unregister(this);
}
@Override
public void onResume() {
super.onResume();
EventBusSingleton.register(this);
}
@Override
public void onDestroy() {
if (realm != null) {
realm.close();
}
super.onDestroy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
Stack Trace
02-08 14:19:58.526 23440-23440/ng.aswitch.shoppar E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
02-08 14:24:27.126 23440-23440/ng.aswitch.shoppar E/AndroidRuntime: FATAL EXCEPTION: main
Process: ng.aswitch.shoppar, PID: 23440
java.lang.NullPointerException
at ng.aswitch.shoppar.fragments.CartFragment$1.onChange(CartFragment.java:66)
at io.realm.HandlerController.notifyGlobalListeners(HandlerController.java:248)
at io.realm.HandlerController.notifyAllListeners(HandlerController.java:323)
at io.realm.HandlerController.realmChanged(HandlerController.java:456)
at io.realm.HandlerController.handleMessage(HandlerController.java:122)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5017)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)
You should add RealmChangeListener
to Realm instance in onCreateView()
instead of onCreate()
, and also remove it in onDestroyView()
.
Because currently if onDestroyView()
is called, and onDestroy()
is not yet called, then if there is a write to the Realm, then RealmChangeListener
will try to update mAdapter
even though the view no longer exists.
Although I think your real problem comes from the fact that
if(!realmResults.isEmpty()){
mRecyclerView.setVisibility(View.VISIBLE);
emptyView.setVisibility(View.GONE);
circularProgessBar.setVisibility(View.GONE);
mAdapter = new BucketFragmentAdapter(realmResults, getActivity(), true);
mRecyclerView.setAdapter(mAdapter);
}else{
mRecyclerView.setVisibility(View.GONE);
emptyView.setVisibility(View.VISIBLE);
}
if RealmResults
is empty, then mAdapter
is not initialized, but if there is a write to the Realm, then RealmChangeListener
will try to update the not-initialized mAdapter
which will result in your crash.
Solution: add null
check to RealmChangeListener
around mAdapter
RealmChangeListener realmChangeListener = new RealmChangeListener() {
@Override
public void onChange(Object element) {
if(mAdapter != null) {
mAdapter.swapData(getPostsFromDb());
}
}
};