【问题标题】:Android fragment not available (leading to crash) when DB results are back当 DB 结果返回时,Android 片段不可用(导致崩溃)
【发布时间】:2017-06-02 08:22:32
【问题描述】:

我有一个包含 2 个片段的应用。单击第一个片段将导致第二个片段触发数据库调用(异步)以从 Firebase DB 获取详细信息。数据库调用完成后,第二个片段将填充数据。问题是当我在 DB 调用仍在进行时单击第二个片段上的后退按钮时。单击后退按钮会导致第一个片段很好,但是当数据库调用返回时应用程序崩溃(发现第二个片段不再可用)。我能够准确地看到(如下所示)代码的哪一部分引发了空指针异常,但我需要帮助来理解处理这个问题的最佳方法。

调用数据库的代码 sn-p

mDatabase = FirebaseDatabase.getInstance().getReference(DBReference);
Query myQuery = mDatabase.orderByChild("title");

    myQuery.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot snapshot) {

            for (DataSnapshot postSnapshot : snapshot.getChildren()) {
                ContactItem post =   postSnapshot.getValue(ContactItem.class);

                ContactItem item = new ContactItem();
                item.status = post.getStatus();
                item.title = post.getTitle();
                itemList.add(item);
            }
            // Transaction complete, sending to listener
            dataListener.newDataReceived(itemList);
        }

第二个 Fragment 中的代码 sn-p 在 DB 操作完成后接收回调。

   public void newDataReceived(ArrayList<ContactItem> itemList) {
    progressCircle.setVisibility(View.GONE);
    adapter = new ContactItemAdapter(this.getActivity(), itemList, contactType);

引发空指针异常的适配器代码

  public ContactItemAdapter(Context context, ArrayList<ContactItem> items, String contactType) {
    mContext = context;
    mDataSource = items;
    mDataSourceCopy = new ArrayList<ContactItem>(mDataSource);
    //Null pointer exception is thrown at below line
    mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    mType = contactType;
  }

【问题讨论】:

  • 您的解决方案就在您的问题中。您的异步任务正在进行中并且您按下返回按钮,如果异步任务仍在进行中,您需要先在返回按钮上停止异步任务。当您在异步任务完成后执行一些 UI 任务时。
  • AsyncTask.cancel() ,这是您取消 asyncTask 的方法。
  • 我可能误认为这是一个异步调用。通过异步,我的意思是应用程序允许用户按下后退按钮,即使在数据库调用正在进行时也是如此。
  • 你想让后退按钮工作还是不工作?
  • 然后你可以覆盖你的 onBackPressed 方法并为你的 Db 调用分配一些布尔状态,并防止用户按下 backButton

标签: android android-fragments android-asynctask


【解决方案1】:

验证您的片段是否已添加到您的 newDataReceived 方法中的活动中。您可以通过在片段的回调中使用isAddedisDetachedisRemoving 来执行此操作。

public void newDataReceived(ArrayList<ContactItem> itemList) {
  if(isAdded()){
    progressCircle.setVisibility(View.GONE);
    adapter = new ContactItemAdapter(this.getActivity(), itemList, contactType);
  }
}

【讨论】:

  • 您能否进一步详细说明。如何检查是否添加了片段? isDetached 和 isRemoving 是标准方法吗?
  • 它们内置在 Fragment 类中,因此您应该能够在来自数据库请求的回调中使用它们。 developer.android.com/reference/android/app/…
  • 谢谢。我试过打印状态,它正确地捕获了片段的状态。我将围绕它构建逻辑。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 2015-02-02
  • 2016-01-25
  • 1970-01-01
  • 2017-05-28
  • 1970-01-01
相关资源
最近更新 更多