【问题标题】:Update views from second Thread in Android Application从 Android 应用程序中的第二个线程更新视图
【发布时间】:2014-07-24 19:37:49
【问题描述】:

在我的应用程序中,同时发生了两件事。在不断转动的activity中有一个时钟指针ImageView,用户也可以按下操作栏按钮。时钟指针的更新大大降低了应用程序的性能,并且按钮需要几秒钟才能响应。我需要能够在另一个线程上运行时钟旋转,但到目前为止我无法完成这一点。

我尝试的第一件事是使用Handler

class MainActivity extends ActionBarActivity() {

  Handler handler;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ...

    handler = new Handler();
    startRotation();
  }

  private void startRotation() {
    Runnable r = new Runnable() {
      // do stuff to the UI here
    };

    handler.postDelayed(r, 100);
  }

}

但由于它在 MainActivity 的线程上运行,它减慢了一切。

接下来,我使用了AsyncTask,但如果不调用,则无法从 AsyncTask 更新 UI:

MainActivity.this.runOnUiThread(new Runnable() {});

它仍然在主线程上运行并降低了应用程序的速度。

所以我的目标是:能够在一个线程上完全更新时钟的指针,这样主线程只用于用户交互,这样它们都可以顺利运行。 p>

谢谢

编辑:

我的时钟分针旋转代码(每 100 毫秒更新一次):

Runnable r = new Runnable() {

  ImageView minute_hand = (ImageView) findViewById(R.id.clock_hand_minute);
  Calendar c = Calendar.getInstance();
  float angle = 360f * ((float) c.get(Calendar.MINUTE) / 60f);
  // minSdk is 11, so this works:
  minute_hand.setRotation(angle);

};

【问题讨论】:

  • 您尝试的第一件事通常是正确的方法。你在做什么来更新计算密集型的时钟?
  • 我同意 Kevin Krumwlede 的评估。你能发布负责绘制时钟指针的代码吗?
  • 如果您只是更改图像,那么您应该在异步任务中进行任何图像加载和图像处理,然后将您创建的图像设置为 ui 线程上的图像视图。在 UI 线程中设置图像不应导致延迟。现在,计算所有像素并改变类似的东西可能......另外,你只以每秒 10 帧的速度更新,UI 应该能够处理这个问题......你的图像更改技术必须非常昂贵。 ..
  • 尝试声明 minute_hand 和 calendar 对象一次,而不是每次运行 r。然后我会尝试 AsyncTask 方法,但在后台线程中进行所有计算,然后在 runOnUIThread 中设置旋转。如果这不起作用,您是否在 ImageView 对象上尝试过动画?

标签: java android multithreading android-asynctask android-handler


【解决方案1】:

如果您正在执行此代码:

ImageView minute_hand = (ImageView) findViewById(R.id.clock_hand_minute);
Calendar c = Calendar.getInstance();
float angle = 360f * ((float) c.get(Calendar.MINUTE) / 60f);
minute_hand.setRotation(angle);

每 100 毫秒,我会说这是矫枉过正。

一般来说,请注意,由于此代码每 100 毫秒在 UI 线程中运行一次,因此它消耗的任何时间片都将从 UI 响应用户交互所需的时间中删除。所以,应该越快越好!

首先,您应该将findViewById(R.id.clock_hand_minute) 代码移到可运行文件之外。在开始时调用一次就足够了,因为视图不会改变。

其次,当一分钟过去时,分针移动6度,这是正确的。但是,您每 100 毫秒或每分钟 600 次执行此操作。这意味着每次非常小旋转(百分之一度)都会更新视图,这可能肉眼几乎看不到,但在绘图方面很耗时。

如果为更新角度设置一个最小阈值可能会好得多。类似的东西

if (angle - lastAngle > THRESHOLD)
    minute_hand.setRotation(angle);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 2013-05-06
    • 2015-10-24
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多