Runnable is posted successfully but not run

ⅰ亾dé卋堺 提交于 2019-11-28 05:22:27

If you look at the docs for View.post there's some relevant info:

This method can be invoked from outside of the UI thread only when this View is attached to a window.

Since you're doing this in onCreate, it is likely that sometimes your View will not be attached to the window yet. You can verify this by overriding onAttachedToWindow and putting something in the logs and also logging when you post. You'll see that when the post fails, the post call happens before onAttachedToWindow.

As the others have mentioned, you can use Activity.runOnUiThread or provide your own handler. However, if you want to do it directly from the View itself, you can simply get the View's handler:

view.getHandler().post(...);

This is especially useful if you have a custom view that includes some sort of background loading. There's also the added bonus of not having to create a new separate handler.

Nik

I extended ImageView class to solve this problem. I collect runnables passed to post while view not attached to window and in onAttachedToWindow post collected runnable.

public class ImageView extends android.widget.ImageView
{
    List<Runnable> postQueue = new ArrayList<Runnable>();
    boolean attached;

    public ImageView(Context context)
    {
        super(context);
    }

    public ImageView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public ImageView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onAttachedToWindow()
    {
        super.onAttachedToWindow();

        attached = true;

        for (Iterator<Runnable> posts = postQueue.iterator(); posts.hasNext();)
        {
            super.post(posts.next());
            posts.remove();
        }
    }

    @Override
    protected void onDetachedFromWindow()
    {
        attached = false;
        super.onDetachedFromWindow();
    }

    @Override
    public boolean post(Runnable action)
    {
        if (attached) return super.post(action);
        else postQueue.add(action);
        return true;
    }
}

I think the problem is you are updating the UI (ImageView) with a separate thread, which is not the UI Thread. The UI can only be updated by the UI Thread.

You can solve this by using Handler:

Handler uiHandler;

public void onCreate(){
    ...
    uiHandler = new Handler(); // This makes the handler attached to UI Thread
    ...
}

Then replace your:

if ( !img.post(new Runnable() {

with

uiHandler.post(new Runnable() {

to make sure the imageview is updated in the UI Thread.

Handler is a quite confusing concept, I also took hours of research to really understand about this ;)

I don't see anything obviously wrong with what you have there; calling View.post() should cause it to run on the UI thread. If your Activity went away (perhaps through a screen rotation), then your ImageView wouldn't be updated, but I would still expect a log entry to say "setting bitmap ...", even if you couldn't see it.

I suggest trying the following and see if it makes a difference:

1) Use Log.d (the standard Android logger) rather that System.out

2) Pass your Runnable to Activity.runOnUiThread() rather than View.post()

Use the following code, can post your code to MainThread anytime anywhere, but not depends any Context or Activity. That can prevent view.getHandler() failure or tedious onAttachedToWindow() stuffs etc.

    new Handler(Looper.getMainLooper()).post(new Runnable() {
        @Override
        public void run() {
            //TODO
        }
    });

I had the same problem, and using view.getHandler() also failed because the handler was not present. runOnUiThread() solved the problem. Presumably this does actually do some queueing until the UI is ready.

The cause for me was calling the icon load task in a base class and the result being returned so quickly that the main class hadnt estabished the view (getView() in fragment).

I'm a bit suspicious that it might spuriously fail sometime. But I'm now ready for it! Thanks guys.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!