Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

@UiThread isn't always on the UI thread #693

Description

@GingerMcMurray

If an instance of an annotated class is created on a thread other than the UI thread, the handler which gets created does not get associated with the UI thread. The generated code is:

private Handler handler_ = new Handler();

This is creating a handler which is tied to the current thread.

According to the docs and a few StackOverflow questions, if it's created like this it'll be guaranteed to be connected to the UI thread:

private Handler handler_ = new Handler(Looper.getMainLooper());

Activity

  1. tbruyelle commented on Aug 9, 2013

    @tbruyelle
    Contributor

    Good point, but I didn't see how it could occur.

    Activities are instantiate by the system, so in the main thread, which is also the case for eventual injected beans. Maybe it could occur when you instantiate annotated fragments, but as it mostly updates the UI, it also runs in the main thread.

  2. GingerMcMurray commented on Aug 9, 2013

    @GingerMcMurray
    Author

    The problem happens when views or fragments are instantiated off of the main thread. This can occur in our application in a couple of ways:

    1. We build screen layouts dynamically based on information pulled from the server. To do this we create views on a background thread and then splice them all together to create a single screen.
    2. We run some button presses as part of a command framework. These commands are running on background threads to prevent ANRs.

    To me the ideal solution would be to ensure that the handler is always attached to the UI thread. If that's not problematic, a fair backup would be to have the build and getInstance methods throw an exception if they're not called on the UI thread. At least that way it's easier to catch the problem.

  3. DayS commented on Aug 11, 2013

    @DayS
    Contributor

    This is a known problem. I remember someone pointing this out, but I can't retrieve the issue right now...
    However, it's should be quite simple to fix.

    For the following code :

    @UiThread
    void emptyUiMethod() {}

    AA will generate this one :

    private Handler handler_ = new Handler();
    
    @Override
    public void emptyUiMethod() {
        handler_.post(new Runnable() { // .... }
    }

    The handler used here is linked to the current thread. We should instantiate it like this : new Handler(Looper.getMainLooper());.
    I don't have enough time to test this, but it should works.

  4. tbruyelle commented on Aug 11, 2013

    @tbruyelle
    Contributor

    Please check that PR above which in my opinion do the job.

  5. DayS commented on Sep 1, 2013

    @DayS
    Contributor

    Merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions