6

我的應用崩潰了。基本上,我有一個片段,其中必須在一個場景中顯示對話框。我通過擴展對話框片段創建了對話框。問題是一些用戶崩潰拋出空指針異常。 這是對話的片段:Android:片段管理器變爲空

VerifyOTPDialog verifyOTPDialog = VerifyOTPDialog.newInstance("Kindly Enter the OTP sent to your Registered Mobile No. :", false, "Verify & Proceed", 
        "home_screen"); 
verifyOTPDialog.show(getFragmentManager(), VerifyOTPDialog.class.getSimpleName()); 

在2號線的應用程序崩潰。從crashlytics,我得到了以下堆棧跟蹤:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()' on a null object reference 
    at android.app.DialogFragment.show(DialogFragment.java:228) 
    at in.droom.fragments.HomeScreenFragment.updateUI(HomeScreenFragment.java:553) 
    at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:626) 
    at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:100) 
    at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1136) 
    at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1094) 
    at android.os.AsyncTask.finish(AsyncTask.java:636) 
    at android.os.AsyncTask.access$500(AsyncTask.java:177) 
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653) 
    at android.os.Handler.dispatchMessage(Handler.java:111) 
    at android.os.Looper.loop(Looper.java:194) 
    at android.app.ActivityThread.main(ActivityThread.java:5637) 
    at java.lang.reflect.Method.invoke(Method.java) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) 

0墜毀:主營:0 0 0x0000000000000000

at android.app.DialogFragment.show(DialogFragment.java:228) 
    at in.droom.fragments.HomeScreenFragment.updateUI(HomeScreenFragment.java:553) 
    at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:626) 
    at in.droom.fragments.HomeScreenFragment.onResponse(HomeScreenFragment.java:100) 
    at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1136) 
    at in.droom.util.DroomApi$1.onPostExecute(DroomApi.java:1094) 
    at android.os.AsyncTask.finish(AsyncTask.java:636) 
    at android.os.AsyncTask.access$500(AsyncTask.java:177) 
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653) 
    at android.os.Handler.dispatchMessage(Handler.java:111) 
    at android.os.Looper.loop(Looper.java:194) 
    at android.app.ActivityThread.main(ActivityThread.java:5637) 
    at java.lang.reflect.Method.invoke(Method.java) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754) 

據我瞭解,該片段經理的某個時間點變得無效。但是,我無法重現該場景。崩潰正在發生到沒有。幾乎每天都有用戶。

更新:(VerifyOtpDialog)

public class VerifyOTPDialog extends DialogFragment implements OnClickListener { 
private static final String TAG_NAME = VerifyOTPDialog.class.getSimpleName(); 
private Context ctx; 
private Dialog dialog; 
private boolean isLaterVisible; 
private String strTitle, strBtnTitle, strFragment = ""; 

private BroadcastReceiver broadcastReceiver; 
private ProfileAddressContactInfoModel userModel; 
private VerifyOTPDialogDismissed verifyOTPDialogDismissed; 
public static final String RECEIVE_OTP = "com.myapp.ACTION_RECEIVED"; 

private ImageView imgViewForClose; 
private RobotoRegularEditTextView editTextForOTP; 
private RobotoBoldTextView btnLater, btnVerifyAndProceed; 
private RobotoLightTextView txtViewForTitle, txtViewForResendOTP; 
public popFragmentListener mPopFragmentListener; 

public VerifyOTPDialog() { 

} 

public static VerifyOTPDialog newInstance(String strTitle, boolean isLaterVisible, String strBtnTitle, String strFragment) { 
    VerifyOTPDialog dialog = new VerifyOTPDialog(); 
    Bundle b = new Bundle(); 
    b.putString("title", strTitle); 
    b.putBoolean("isLaterVisible", isLaterVisible); 
    b.putString("btnTitle", strBtnTitle); 
    b.putString("strFrom", strFragment); 
    dialog.setArguments(b); 
    return dialog; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ctx = getActivity(); 
    registerReceiver(); 
} 

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 
    dialog = super.onCreateDialog(savedInstanceState); 
    dialog.setOnKeyListener(new OnKeyListener() { 
     @Override 
     public boolean onKey(android.content.DialogInterface dialog, int keyCode, android.view.KeyEvent event) { 
      if ((keyCode == android.view.KeyEvent.KEYCODE_BACK)) { 
       AppUtil.hideKeyboard(); 
       return true; 
      } else 
       return false; 
     } 
    }); 

    return dialog; 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.verify_otp_popup, container, false); 
    Bundle b = getArguments(); 
    strTitle = b.getString("title"); 
    isLaterVisible = b.getBoolean("isLaterVisible"); 
    strBtnTitle = b.getString("btnTitle"); 
    strFragment = b.getString("strFrom"); 
    getDialog().setCanceledOnTouchOutside(false); 
    getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE); 
    getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(0)); 

    userModel = AppUtil.getUserProfile(); 

    imgViewForClose = (ImageView) view.findViewById(R.id.imgViewForClose); 
    editTextForOTP = (RobotoRegularEditTextView) view.findViewById(R.id.editTextForOTP); 
    btnLater = (RobotoBoldTextView) view.findViewById(R.id.btnLater); 
    btnVerifyAndProceed = (RobotoBoldTextView) view.findViewById(R.id.btnVerifyAndProceed); 
    txtViewForTitle = (RobotoLightTextView) view.findViewById(R.id.txtViewForTitle); 
    txtViewForResendOTP = (RobotoLightTextView) view.findViewById(R.id.txtViewForResendOTP); 

    if (userModel != null) 
     txtViewForTitle.setText(strTitle + " +91 " + userModel.getContactInfo().getMobilePhone()); 

    txtViewForResendOTP.setText(getUnderlinedContent()); 

    if (!isLaterVisible) 
     btnLater.setVisibility(View.GONE); 

    btnVerifyAndProceed.setText(strBtnTitle); 

    imgViewForClose.setOnClickListener(this); 
    txtViewForResendOTP.setOnClickListener(this); 
    btnLater.setOnClickListener(this); 
    btnVerifyAndProceed.setOnClickListener(this); 

    return view; 
} 

public interface VerifyOTPDialogDismissed { 
    void dialogDismissing(String... s); 
} 

@Override 
public void onDismiss(DialogInterface dialog) { 
    super.onDismiss(dialog); 
} 

public VerifyOTPDialogDismissed getDialogDismissListener() { 
    return verifyOTPDialogDismissed; 
} 

public void setDialogDismissListener(VerifyOTPDialogDismissed VerifyOTPDialogDismissed) { 
    this.verifyOTPDialogDismissed = VerifyOTPDialogDismissed; 
} 

private void registerReceiver() { 
    IntentFilter intentFilter = new IntentFilter(); 
    intentFilter.addAction(RECEIVE_OTP); 

    broadcastReceiver = new BroadcastReceiver() { 
     @Override 
     public void onReceive(Context context, Intent intent) { 
      String strOTP = intent.getExtras().getString("otp"); 

      if (strOTP != null && editTextForOTP != null) 
       editTextForOTP.setText(strOTP); 
     } 
    }; 

    ctx.registerReceiver(broadcastReceiver, intentFilter); 
} 

private SpannableString getUnderlinedContent() { 
    SpannableString content = new SpannableString(getResources().getString(R.string.resend_otp)); 
    content.setSpan(new UnderlineSpan(), 0, content.length(), 0); 
    content.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.blue_button)), 0, content.length(), 0); 
    return content; 
} 

private void sendOTP(HashMap<String, String> params) { 
    Response.Listener<JSONObject> responseListener = new Response.Listener<JSONObject>() { 
     @Override 
     public void onResponse(JSONObject response) { 
      try { 
       Logger.debugMessage("Response Object", response.toString()); 
       String responseCode = response.getString("code"); 

       if (responseCode.equalsIgnoreCase("success")) { 
        String message = response.getString("message"); 
        Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show(); 
       } else if (responseCode.equalsIgnoreCase("failed")) { 
        if (response.has("error")) { 
         if (response.has("error_code")) { 
          String error_code = response.optString("error_code"); 
          displayMessageAlert(response.optString("error"), "", error_code); 
         } else { 
          displayMessageAlert(response.optString("error"), "", ""); 
         } 
        } else if (response.has("errors")) { 
         JSONArray errorsArray; 
         try { 
          errorsArray = response.getJSONArray("errors"); 
          Toast.makeText(ctx, errorsArray.getString(0), Toast.LENGTH_SHORT).show(); 
         } catch (JSONException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 

    Response.ErrorListener errorListener = new Response.ErrorListener() { 
     @Override 
     public void onErrorResponse(VolleyError error) { 

     } 
    }; 

    Api.sendOTP(params, responseListener, errorListener); 
} 

private void verifyOTP(HashMap<String, String> params, final String strFragment) { 
    Response.Listener<JSONObject> responseListener = new Response.Listener<JSONObject>() { 
     @Override 
     public void onResponse(JSONObject response) { 
      try { 
       Logger.debugMessage("Response Object", response.toString()); 
       String responseCode = response.getString("code"); 

       if (responseCode.equalsIgnoreCase("success")) { 
        if (userModel != null) { 
         userModel.setPhoneVerified(true); 
         userModel.setOTPVerified(true); 
         AppUtil.saveUserProfile(userModel); 
        } 

        VerifyOTPDialog.this.dismissAllowingStateLoss(); 
        String event_name = ""; 
        if (strFragment.equalsIgnoreCase("SellFragment")) { 
         event_name = "otp_verified_on_sell"; 
         MainActivity.getInstance().pushFragment(SellFragment.newInstance(), SellFragment.class.getSimpleName(), true); 
        } else if (strFragment.equalsIgnoreCase("QuickSellFragment")) { 
         event_name = "otp_verified_on_quick_sell"; 
         MainActivity.getInstance().pushFragment(new QuickSellFragment(), QuickSellFragment.class.getSimpleName(), true); 
        } else if (strFragment.equalsIgnoreCase("gotoPaymentFlow")) { 
         event_name = "otp_verified_on_payment"; 
         DraftSummaryFragment.getInstance().gotoPaymentFlow(); 
        } else if (strFragment.equalsIgnoreCase("gotoPlaceBidPage")) { 
         event_name = "otp_verified_on_place_bid"; 
         verifyOTPDialogDismissed.dialogDismissing(strFragment); 
        } else if (strFragment.equalsIgnoreCase("make_best_offer")) { 
         event_name = "otp_verified_on_make_best_offer"; 
         verifyOTPDialogDismissed.dialogDismissing(strFragment); 
        } else if (strFragment.equalsIgnoreCase("checkAvailableFees")) { 
         event_name = "otp_verified_on_quick_sell"; 
         QuickSellDraftSummaryFragment.getInstance().checkAvailableFees(); 
        } else if (strFragment.equalsIgnoreCase("home_screen")) { 
         event_name = "otp_verified_for_casual_seller"; 
        } else if (strFragment.equalsIgnoreCase("my_profile")) { 
         event_name = "otp_verified_from_my_profile"; 
        } else if (strFragment.equalsIgnoreCase("my_profile")) { 
         event_name = "otp_verified_from_my_profile"; 
        } else if (strFragment.equalsIgnoreCase("pro_seller_profile_settings")) { 
         event_name = "otp_verified_from_pro_seller_profile_settings"; 
        } else if (strFragment.equalsIgnoreCase("pro_seller_welcome")) { 
         event_name = "otp_verified_from_pro_seller_welcome"; 
        } else if (strFragment.equalsIgnoreCase("seller_badges")) { 
         event_name = "otp_verified_from_seller_badges"; 
        } else if (strFragment.equalsIgnoreCase("trust_factor")) { 
         event_name = "otp_verified_from_trust_factor"; 
        } else if (strFragment.equalsIgnoreCase("ProSellerDashboard")) 
         MainActivity.getInstance().pushFragment(ProSellerDashboardFragment.newInstance(false), ProSellerDashboardFragment.class.getSimpleName(), true); 
        else 
         event_name = "otp_verified_from_my_account"; 

        JSONObject post = BetaOutAPIs.getPostDataForUserAdd(userModel, "update"); 
        JSONArray eventArray = new JSONArray(); 
        JSONObject event = new JSONObject(); 
        event.put("name", event_name); 
        event.put("timestamp", String.valueOf(System.currentTimeMillis()/1000)); 
        eventArray.put(event); 
        post.put("events", eventArray); 
        BetaOutAPIs.sendEventToBetaOut(post, TAG_NAME); 
        BaseApplication.getInstance().trackMoEngageEvents(event_name, new PayloadBuilder().build()); 
       } else if (responseCode.equalsIgnoreCase("failed")) { 
        btnVerifyAndProceed.setEnabled(true); 
        if (response.has("error")) { 
         if (response.has("error_code")) { 
          String error_code = response.optString("error_code"); 
          displayMessageAlert(response.optString("error"), "", error_code); 
         } else { 
          displayMessageAlert(response.optString("error"), "", ""); 
         } 
        } else if (response.has("errors")) { 
         Toast.makeText(ctx, response.optString("errors"), Toast.LENGTH_SHORT).show(); 
        } 
       } 
      } catch (JSONException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 

    Response.ErrorListener errorListener = new Response.ErrorListener() { 
     @Override 
     public void onErrorResponse(VolleyError error) { 
      error.printStackTrace(); 
     } 
    }; 

    Api.verifyOTP(params, responseListener, errorListener); 
} 

private boolean validateOTP() { 
    String validationMessage = ""; 
    boolean isValid = true; 
    String email = editTextForOTP.getText().toString(); 

    if (email.length() == 0) { 
     isValid = false; 
     validationMessage = "Please Enter OTP"; 
     Toast.makeText(getActivity(), validationMessage, Toast.LENGTH_SHORT).show(); 
    } 

    return isValid; 
} 

@Override 
public void onClick(View v) { 
    switch (v.getId()) { 
     case R.id.imgViewForClose: 
      VerifyOTPDialog.this.dismissAllowingStateLoss(); 
      break; 

     case R.id.txtViewForResendOTP: 
      if (userModel != null) { 
       HashMap<String, String> params = new HashMap<String, String>(); 
       params.put("user_id", AppSharedPref.getUserId()); 
       params.put("phone", userModel.getContactInfo().getMobilePhone()); 
       sendOTP(params); 
      } 
      break; 

     case R.id.btnLater: 
      VerifyOTPDialog.this.dismissAllowingStateLoss(); 

      if (mPopFragmentListener != null) 
       mPopFragmentListener.gotoRootFragment(); 
      if (strFragment.equalsIgnoreCase("SellFragment")) { 
         MainActivity.getInstance().pushFragment(SellFragment.newInstance(), SellFragment.class.getSimpleName(), true); 
      } else if (strFragment.equalsIgnoreCase("QuickSellFragment")) { 
       MainActivity.getInstance().pushFragment(new QuickSellFragment(), QuickSellFragment.class.getSimpleName(), true); 
      } else if (strFragment.equalsIgnoreCase("gotoPlaceBidPage")) { 
       //verifyOTPDialogDismissed.dialogDismissing(); 
      } else if (strFragment.equalsIgnoreCase("ProSellerDashboard")) 
         MainActivity.getInstance().pushFragment(ProSellerDashboardFragment.newInstance(false), ProSellerDashboardFragment.class.getSimpleName(), true); 
      break; 

     case R.id.btnVerifyAndProceed: 
      if (validateOTP()) { 
       btnVerifyAndProceed.setEnabled(false); 
       HashMap<String, String> map = new HashMap<String, String>(); 
       map.put("user_id", SharedPref.getUserId()); 
       map.put("code", editTextForOTP.getText().toString()); 
       verifyOTP(map, strFragment); 
      } 
      break; 

     default: 
      break; 
    } 
} 

protected void displayMessageAlert(String message, String title, final String error_code) { 
    String s = "Alert"; 
    if (title != null && title.length() > 0) { 
     s = title; 
    } 

    if (message != null) { 
     new AlertDialog.Builder(ctx).setTitle(s).setMessage(message) 
       .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int which) { 
         if (error_code.toLowerCase().equals("logout")) { 
          AppUtil.logoutUser((MainActivity) ctx); 
          MainActivity.getInstance().pushFragment(LoginFragment.newInstance(true, true), LoginFragment.class.getSimpleName(), true); 
         } 
         dialog.dismiss(); 
        } 
       }).show(); 
    } 
} 

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

    if (broadcastReceiver != null) { 
     ctx.unregisterReceiver(broadcastReceiver); 
    } 
} 

public void setPopFragmentListener(popFragmentListener mPopFragmentListener) { 
    this.mPopFragmentListener = mPopFragmentListener; 
} 

public interface popFragmentListener { 
    void gotoRootFragment(); 
} 
} 
+0

你可以請把你的VerifyOTPDialog在這裏 –

+0

你在調用show()在片段? –

+0

你是否在異步任務中調用'show'? – g4s8

回答

4

你應該之前得到片段經理:

FragmentManager fragMan = getSupportFragmentManager();

然後測試它的無效

if(fragMan != null){ 
    // Do stuff 
} 

如果你是如果在使用在的AsyncTask的DoInBackground你應該得到的Uithread:

runOnUiThread(new Runnable() { 
    public void run() { 
     // do stuff on the ui like display fragments 
    } 
}); 

編輯:

您應該使用支持V4庫支持片段

0

如果從片段顯示,然後使用getChildFragmentManager()

Like:

verifyOTPDialog.show(getChildFragmentManager(),VerifyOTPDialog.class.getSimpleName()); 
+0

但是可以從API 17中獲得。此外,我正在使用android.app.fragment – Nitish

+0

然後,您必須使用'android.support.v4.app.dialogFragment'作爲DialogFragment,並使用'android.support.v4.app .Fragment'。您必須在活動中擴展「FragmentActivity」或「AppCompatActivity」。這樣你可以在api 17下面的Fragment中獲得'getchildFragmentManager()'。 –

1

你說你使用android.app.fragment來承載你的片段。由於您使用android DialogFragment創建對話框,因此Fragment對話框本身就是一個片段,因此使得這成爲android中嵌套Fragments的一種情況。當我們嵌套我們使用的折扣getChildFragmentManager().

支持android中的嵌套片段在API 11中不可用。嵌套片段的支持從API 17開始。如果你想在API 11-16中使用嵌套的片段,那麼你必須使用支持庫片段。

所以,你必須讓你的android.support.v4.app.dialogFragment型DialogFragment和你的類型android.support.v4.app.fragment

0

我會建議調用DialogFragment從父活動,這樣你就不會遇到與該片的生命週期問題的片段。由於您可能試圖讓片段彼此通信,因此應通過活動完成。

下面是詳細信息 - https://developer.android.com/training/basics/fragments/communicating.html

操作如下:

  1. 定義接口
  2. 實現接口
  3. 郵件傳遞到片段

最後步驟是您可以調用DialogFragment然後進行撥號的位置og將數據返回到活動中,然後將其傳遞給調用的Fragment。