【问题标题】:Checking for null with RealmChangeListener使用 RealmChangeListener 检查 null
【发布时间】:2017-02-08 19:20:01
【问题描述】:

当 RealmList 为空时,我的应用程序崩溃。它运行良好,直到我将模拟器从 API 23 更改为 API 19。

我已经进行了检查,但它没有,但仍然出现崩溃。我试过这样做

RealmChangeListener realmChangeListener = new RealmChangeListener() {
@Override
public void onChange(Object element) {
   if(getPostsFromDb() != null){
      mAdapter.swapData(getPostsFromDb());      
    }
  }
};

应用仍然会因 NPE

而崩溃

我该如何解决这个问题?

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);
  }

}

堆栈跟踪

    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)

【问题讨论】:

  • 什么是堆栈跟踪
  • @EpicPandaForce 我已经更新了问题并添加了堆栈跟踪

标签: android fragment realm realm-list


【解决方案1】:

您应该将RealmChangeListener 添加到onCreateView() 中的Realm 实例而不是onCreate(),并在onDestroyView() 中删除它。

因为当前如果onDestroyView() 被调用,而onDestroy() 还没有被调用,那么如果有一个对领域的写入,那么RealmChangeListener 将尝试更新mAdapter,即使视图不再存在。


虽然我认为你真正的问题来自于

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);
}

如果RealmResults 为空,则mAdapter 未初始化,但如果有写入Realm,则RealmChangeListener 将尝试更新未初始化的mAdapter,这将导致您的崩溃。


解决方案:在mAdapter周围添加null检查到RealmChangeListener

RealmChangeListener realmChangeListener = new RealmChangeListener() {
    @Override
    public void onChange(Object element) {
        if(mAdapter != null) {
            mAdapter.swapData(getPostsFromDb());
        }
    }
};

【讨论】:

  • 成功了,非常感谢。但是,行为发生了变化,我的片段确实像以前一样立即更新,直到我将片段留给另一个片段并在片段自行更新之前返回片段,对此有什么解决方法。
  • onCreateView()onViewCreated() 中调用BucketListAPIHelper.loadBucket(user_id);
  • 我都试过了,但仍然没有工作,直到离开并返回片段,片段只有在我可能删除列表中的项目或删除该片段中的所有列表时才会更新。
  • 然后重新初始化你的适配器,调用notifyDataSetChanged(),等等
猜你喜欢
  • 1970-01-01
  • 2012-01-02
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多