Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is runnable callbacks destroying activity automatically?

I wanted to know if there is a possibility that we could handle/detect runnable callbacks with delay (postDelayed method) on android?

For example, I have one or several splashscreen (which runs with handler.postDelayed(new Runnable()...) on my application (application for testing purpose). In this application I have also a library (that I am creating and using it in the application) and some classes that are available there which runs on an IntentService class.

Sometimes, when the application is running those splashscreen Activities (for Testing purpose), the library that I am creating, might popup some activities automatically in the UI. But it appears that if those activities comes on a splashscreen activity and that the splashscreen is being destroyed, those activities (that popup automatically) will also be destroyed and logging a "leaked window" message in the logcat.

The problem is that :

  • those activities that appears automatically in the UI should not be closed automatically, this is prohibited. It needs an interaction from the user for closing that activity and returns to the normal behaviour of the application.
  • Also, the library doesn't know anything about the UI of the application.

So my questions are (relatively to the library side that I am creating without having informations to the flow of the UI application):

  • Is there a way to detect if some postDelayed method was created in the application relatively to the Library side ? If yes, how could I handle the problem ?

P.S.: Notice that normally, I am using a Dialog for the suppose Activity who is appearing automatically.

UPDATE

Diagram

Explanation of the diagram :

Right now I have a case that a Splashscreen is being executed.

The class which extends the IntentService class, has received a Request from internet which will start an Activity.

Meanwhile the splashscreen is on postdelayed, the other Activity has been created and is showing in the UI. When X seconds has passed and the other Activity hasn't been destroyed, the Next Activity is created and destroy the other Activity automatically. In doing that, Android throws a "leaked window" message relatively to the Activity.

like image 509
Damiii Avatar asked Aug 16 '17 09:08

Damiii


People also ask

How do I dispose of handler Android?

In the dispose() method you should cleanup the workerHandler before disposing of the model. See the removeCallbacks or removeCallbacksAndMessage(null) methods in the Handler class. The latter method removes all callbacks and messages when the argument is null . workerHandler is type of Handler.

What is a callback in Android?

Callbacks are cool Callbacks are all over the place in Android Development. That's simply because they do a job, and they do it well! By definition: A callback is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.

How do I stop runnable?

You need to create your own interface that extends Runnable and adds a (public) kill() method.

What is an activity which method is implemented by all subclasses of an activity?

An activity represents a single screen with a user interface just like window or frame of Java. Android activity is the subclass of ContextThemeWrapper class. The Activity class defines the following call backs i.e. events. You don't need to implement all the callbacks methods.


1 Answers

Is there a way to detect if some postDelayed method was created in the application relatively to the library side?

You can make use of MessageQueue.IdleHandler API. See LooperIdlingResource how espresso finds out whether it is appropriate time to fire in assertion.


    @Override
    public boolean queueIdle() {

      QueueState queueState = myInterrogator.determineQueueState();
      if (queueState == QueueState.EMPTY || queueState == QueueState.TASK_DUE_LONG) {
        ...
      } else if (queueState == QueueState.BARRIER) {
        ...
      }

      return true;
    }

This will help you to understand whether there is a message in the MessageQueue, but it won't tell you what exact message is there.

The solution I'd go with would be to unschedule the Runnable that you have postDelayed within onStop of the activity, because if Activity (the one from library) has been launched, than onStop of SplashScreen is being called:


public class SplashActivity extends AppCompatActivity {

  private final Runnable myRunnable = () -> {
    // launch `NextActivity`
  };
  private final Handler handler = new Handler();

  @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    handler.postDelayed(myRunnable, 3000);
  }

  @Override
  protected void onStop() {
    super.onStop();
    handler.removeCallbacks(myRunnable);
  }

}

like image 75
azizbekian Avatar answered Nov 11 '22 09:11

azizbekian