BroadcastReceiver context with dialog

2019-07-26 14:09发布

问题:

I'm trying to achieve the following

  1. An Activity starts a background task (SyncAdapter) and shows a dialog.
  2. The background task sends broadcasts.
  3. These broadcasts should be intercepted by the dialog.

What I would expect is this:

Dialog           Broadcast
  <-------------------
 OK!
  <-------------------
 OK!

         ....

  <-------------------
 OK!

But what I get is this:

Dialog           Broadcast
  <-------------------
  <-------------------

         ....

  <-------------------

    (dialog dismiss)

 OK!
 OK!

         ....
 OK!

As the diagram shows, the broadcasts are being sent correctly, but they are being received only after the dialog is dismissed. I want to receive them when the dialog is being shown. In other words, steps 1 and 2 are working fine, but 3. is working partially. What I think might be the problem is that I'm not using the proper context for the BroadcastReceiver.

So my question is: Which context should I use to subscribe for updates (i.e. receive the broadcasts, not send them), so that they can be picked up by the dialog when it is being shown?

I've tried with Activity.this, Activity.this.getBaseContext() and Activity.this.getApplicationContext(), dialog.getContext(), DialogFragment.getActivity() to no avail.

Just to clarify: I've used the BroadcastReceiver pattern multiple times, I'm just having trouble when using it alongside a dialog.

回答1:

FACTS:

  • ACTIVITY (A) shows DIALOG (D)
  • unknown type of (SOMETHING) named BACKGROUND TASK (T)
  • (T) SENDS BROADCAST TO BROADCASTRECEIVER (R)
  • (R) SHOULD DISMISS (D)

QUESTIONS:

  • (T) do you mean CLASS DERIVED from AbstractThreadedSyncAdapter?
  • do you somehow finish (A) after start of (T) and show (D)?

CONCLUSION:

  • regardless what you do if your (A) create and shows (D) it is responsible to dismiss (D) & to do it before gets in onStop() state
  • other words if activity will die without dismissed dialog you will get
android.view.WindowLeaked exception will be thrown.
  • & when you try manipulate the dialog you will get:
java.lang.IllegalArgumentException: View not attached to window manager

The second part of your question, which concerns context

  • you always can check which context is assigned to Dialog by method
Dialog.getContext()
  • usen it to match other context
Dialog.getContext().equals(Context);
  • also u can use Class method
Class.isAssignableFrom(Class<?> c)
  • if u wanna match context to class (for example Activity u use)
MyActivity.class.isAssignableFrom(ObjectToMatch.getClass());

and I would forget to add:

you can always START DIALOG USING APPLICATION CONTEXT :)

& one more thing:

any stuff involving UI should by done on UI THREAD in case you will forgot & get

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

edit:

I DON'T SEE ANY PROBLEM : WORKING SOLUTION



回答2:

This is a BroadcastReceiver and you adapt it on your code. Instead of Activity.this, Activity.this.getBaseContext() and Activity.this.getApplicationContext() you should use Context like this :

class BroadCastReceiverTest extends BroadcastReceiver {
Context context;
public void onReceive(Context c, Intent intent) {
    this.context = c;

}

Now you have to use this.context as a Context.



回答3:

Try Otto

https://github.com/square/otto

From documentation,

An enhanced Guava-based event bus with emphasis on Android support.

Otto is an event bus designed to decouple different parts of your application while still allowing them to communicate efficiently.

Forked from Guava, Otto adds unique functionality to an already refined event bus as well as specializing it to the Android platform.