android - 调用 onClick 时更改 ImageButton 的图像

标签 android android-widget

我有一个 ImageButton,它在单击时执行长时间运行的操作。所以我没有成功尝试做的是在 onClick 调用开始时更改图像并在结束时将其更改回来。

我已经尝试了下面的代码,但我发现 android 在 onClick 完成后重绘了按钮图像,所以它没有用。

如果可能的话,我也愿意采用其他方式来做到这一点。

下面是我使用的代码 fragment 。 Thread.sleep 表示长时间运行的操作。我希望在执行进入休眠状态时看到图像发生变化,而不是在 onClick 完成之后。

btnTest = (ImageButton) findViewById(R.id.btnTest);
btnTest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
    System.out.println("start");
    btnTest.setImageResource(R.drawable.add);
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
    }

    System.out.println("end");
    btnTest.setImageResource(R.drawable.del);
}
});

最佳答案

您的问题是您sleep() 在(或以其他方式阻塞)UI 线程上。请理解主/UI 线程负责重绘和所有事件处理。如果您在那里休眠(onClick() 在 UI 线程上执行),那么 Android 将无法执行与用户界面相关的任何操作。

背景是多线程 GUI 效率极低。大多数与 UI 相关的调用,例如 setBackground,只是设置一些数据或什至安排更多 Activity ,不会立即生效,只有当控件返回到主 UI 线程控制循环时才会产生结果,例如进行协调重绘。试想一下,如果您一个接一个地启动几个布局更改,并且每个布局更改都会立即得到处理,会发生什么情况——这将导致大量的计算,这些计算将在下一刻变得无效。

所以主线程只不过是一个处理各种回调的巨大循环,包括 Activity 生命周期方法、事件监听器回调等。所以如果你愿意,UI 是单线程的。

您需要做的是在 AsyncTask 或 Thread 上执行长时间运行的操作。对于初学者,我会尝试 AsyncTask。在 AsyncTask 的 onPostExecute() 方法中,它再次在 UI 线程上运行,您可以随意操作您的用户界面。

为了快速成功,您还可以使用线程:

@Override
public void onClick(View v) {
    // on UI thread
    btnTest.setImageResource(R.drawable.add);
    // launch concurrent thread
    (new Thread(new Runnable() {
            @Override
            // the code of this method will run concurrently
            public void run() {
                System.out.println("start");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {}
                System.out.println("end");
                // at this point, we need to get back to the UI thread
                // for simplicity, we use the view's convenience method for that
                v.post(new Runnable() {
                    @Override
                    // the code of this method will run on the UI thread
                    public void run() {
                       btnTest.setImageResource(R.drawable.del);
                    }
                })
            }
        })
    ).start();
}

AsyncTask 看起来好多了,但它不容易创建和即时使用。

请注意,上面的代码创建了一个 Thread,它会一直运行,直到它离开它的 run() 方法,或者 Android 终止托管您的应用程序的 Linux 进程。

另请注意,此线程包含对代码中许多对象的引用,因为它可以访问其周围范围内的所有内容。

结论是,如果您的 Thread 确实运行了很长时间,它可能会持有对甚至不再可见的 View 的引用,因此僵尸内存对象可能会加剧您应用的资源消耗。

此外,您提到您正在那里进行长时间运行的操作。问题是,该操作是等待 还是计算 某些东西。如果它计算某些东西,你可能会发现它现在需要十倍的时间,除非你 adjust the AsyncTask/Thread priority as described here .

关于android - 调用 onClick 时更改 ImageButton 的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16032349/

相关文章:

Android 应用不应在接收 Intent 时启动

java - 在 SDK 1.5、API 3 中自定义 TabWidget

android - 背景图像交叉淡入淡出

android - 加载 WebView 会阻止布局中加载其他 View

android - 在android中绘制一条平滑的线并逐渐变小

android - 如何在我的 ListView 上启用 LongCLicks?

android - 如何提升ViewFlipper/ViewAnimator的性能

java - 从另一个 Android 应用程序将数据插入数据库

android - 整洁架构 : Use CompositeDisposable in domain or presentation/app

java - 如何找出 Android 相机的光圈角度