1

I'm running an application that generates a dialog alert from within a Fragment as a network callback. This requires you to pass in an available Context reference; since I'm using Fragments, I use getActivity(). Due to the network-dependent nature of the callback, getActivity() can sometimes return null. This crashes my code.

To work around this error, I was hoping to supply the ApplicationContext to the dialog instead. It is a singleton that persists for the lifetime of the application, so I know it won't be withdrawn. In addition, the Dialog's content is with regards to payment confirmation, so I believe there's reasonable scope for it to be displayed without a strict relationship to a certain Window.

Is this a safe implementation? Am I avoiding the inevitable, and should move to a more robust pattern altogether?

Mapsy
  • 4,192
  • 1
  • 37
  • 43
  • @PankajKumar It works on a Galaxy S6, and on emulated API 24, so far. I'll keep testing lower API levels. – Mapsy Jun 02 '17 at 12:21
  • It will work ofcourse, but it opens to even weirder problems in the long run- You are memmory leaking if you pass Context and then go to another screen. It might also crash if you minimize the app – X3Btel Jun 02 '17 at 12:24

2 Answers2

2

Is this a safe implementation?

IMHO, no.

Tactically, I would expect your app to crash in some situations (e.g., your app is in the background at the time the network I/O completes), and I would expect your dialog to not necessarily honor the appropriate theme. Since it seems like your "dialog" is not tied to an activity, it should be an activity, in the form of a dialog-themed activity. That solves your reliability problem and your theme problem, though there is still the possibility that you display a dialog(-themed activity) while the user is in some other app, if your network I/O takes longer than you anticipate.

Strategically, it seems like you care about the results of your network I/O regardless of what happens in the UI layer of your app. In that case, your UI layer of your app should not be the one directly receiving the results of the network I/O, and it feels like your fragment is doing that right now. Use something that is decoupled from your UI (IntentService, JobService, bare thread, ThreadPoolExecutor) for managing the network I/O. Have it use an event bus (LocalBroadcastManager, greenrobot's EventBus) to tell the UI layer that the network I/O completed, and if the UI layer does not respond to the event (because it is in the background and you only pay attention to events when the UI is visible), raise a Notification or do something else subtle to let the user know about the results.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Using `EventBus` to return crucial event data back to the owning `Activity` was a brilliant suggestion. Thanks! – Mapsy Jun 06 '17 at 08:07
1

You have to use an Activity as Context for your Dialog, because Dialog is a component, that expects the UI context. So before showing the dialog, you can check if the current fragment is currently added to its activity using the isAdded() method:

if (isAdded()) {
    showDialog();
} 
makovkastar
  • 5,000
  • 2
  • 30
  • 50
  • Thanks man. Unfortunately this wouldn't work. The dialog informs users that their payment was successful, and prevents them from attempting re-purchasing even though it has gone through. We need this dialog every single time! Ideally some kind of callback for when `isAdded` would return true would be great to launch the message, if the `Context` weren't available. – Mapsy Jun 02 '17 at 13:51