可运行已成功发布但未运行

2022-09-01 17:59:46

在现有的Android项目中,我遇到了以下代码片段(我在其中插入了调试垃圾)

ImageView img = null;

public void onCreate(...) {

    img = (ImageView)findViewById(R.id.image);

    new Thread() {
        public void run() {
            final Bitmap bmp = BitmapFactory.decodeFile("/sdcard/someImage.jpg");
            System.out.println("bitmap: "+bmp.toString()+" img: "+img.toString());
            if ( !img.post(new Runnable() {
                public void run() {
                    System.out.println("setting bitmap...");
                    img.setImageBitmap(bmp);
                    System.out.println("bitmap set.");
                }
            }) ) System.out.println("Runnable won't run!");
            System.out.println("runnable posted");
        }
    }.start();

Android开发的新手,并且已经搜索过,我知道这是在不阻塞主(UI)线程的情况下完成工作的方法,同时在解码后仍然在UI线程上设置图像。(至少根据Android开发人员)(我已经通过在各个地方登录来验证)Thread.currentThread().getName()

现在有时图像只是没有显示出来,stdout只说

I/System.out( 8066): bitmap: android.graphics.Bitmap@432f3ee8 img: android.widget.ImageView@4339d698
I/System.out( 8066): runnable posted

没有来自Runnable的消息的跟踪。所以看起来Runnable没有,尽管返回。将 ImageView 拉入并声明它没有帮助。run()img.post()trueonCreate()final

我无能为力。只需直接设置位图,同时阻止 UI 线程,就可以解决问题,但我想把事情做好。有人明白这是怎么回事吗?

(ps. 这一切都是在 Android 1.6 手机和 android-3 sdk 上观察到的)


答案 1

如果您查看文档以获取 View.post 会有一些相关信息:

仅当此视图附加到窗口时,才能从 UI 线程外部调用此方法。

由于您正在 中执行此操作,因此有时您可能还没有连接到窗口。您可以通过覆盖AttachedToWindow并在日志中放入某些内容并在发布时进行日志记录来验证这一点。您将看到,当发布失败时,发布调用发生在 之前。onCreateViewonAttachedToWindow

正如其他人所提到的,您可以使用Active.runOnUiThread或提供自己的处理程序。但是,如果您想直接从自身执行此操作,则可以简单地获取 的处理程序:ViewView

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

如果您有一个包含某种后台加载的自定义视图,这将特别有用。还有一个额外的好处,即不必创建新的单独处理程序。


答案 2

我认为问题是你用一个单独的线程更新UI(ImageView),这不是UI线程。UI 只能由 UI 线程更新。

您可以使用处理程序解决此问题:

Handler uiHandler;

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

然后替换您的:

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

uiHandler.post(new Runnable() {

以确保在 UI 线程中更新图像视图。

汉德勒是一个相当令人困惑的概念,我也花了几个小时的研究来真正理解这个;)


推荐