AsyncTask 执行时方向更改会中断禁用按钮

发布于 2024-11-17 00:56:53 字数 290 浏览 3 评论 0原文

我有一个 Activity,它开始执行 AsyncTask 以响应单击 Button 小部件。我使用 setEnabled(false) 单击按钮时禁用该按钮。 AsyncTask 在完成时调用 Activity 上的回调方法。我在回调中对 Button 调用 setEnabled(true) ,以在 AsyncTask 完成时重新启用 Button。这一切都工作正常,直到 AsyncTask 执行时方向发生变化。我尝试了很多不同的方法来让按钮在发生这种情况时正确启用/禁用,但我无法使其正常工作。即使 AsyncTask 执行时方向发生变化,正确的方法是什么?

I have an Activity that begins executing an AsyncTask in response to clicking a Button widget. I disable the Button when it's clicked using setEnabled(false). The AsyncTask calls a callback method on the Activity when it completes. I call setEnabled(true) on the Button in the callback to re-enable the Button when the AsyncTask is done. This all works fine until the orientation changes while the AsyncTask is executing. I've tried lots of different things to get the Button to be enabled/disabled properly when this happens and I can't make it work right. What is the correct way to make this work even if the orientation changes while the AsyncTask is executing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ι不睡觉的鱼゛ 2024-11-24 00:56:53

当应用程序中的方向发生变化时,再次调用 onCreate 方法,并且您已在 onCreate 方法中编写了所有逻辑。因此,当方向改变时,使您的应用程序不进入 onCreate() 方法

将以下内容添加到清单中的活动声明中:

android:configChanges="orientation"

所以它看起来像

<activity android:label="@string/app_name" 
        android:configChanges="orientation|keyboardHidden" 
        android:name=".your.package">

When orientation chaneg in your application onCreate method is called again and you have written all the logic in onCreate method. so make your application not to come to onCreate() method when orientation changes

Add the following to the activity declaration in the manifest:

android:configChanges="orientation"

so it looks like

<activity android:label="@string/app_name" 
        android:configChanges="orientation|keyboardHidden" 
        android:name=".your.package">
明天过后 2024-11-24 00:56:53

我不认为您需要开始拦截方向变化。如果你真的想做一些事情,比如为不同的方向加载不同的资源,它会偷工减料,并且可能会给你带来很多麻烦。

根本问题是 AsyncTask 对其要更新的按钮的引用已过时,它引用了您的旧按钮。解决这个问题的办法是实现Activity.onRetainNonConfigurationInstanceState()。在发生方向变化的情况下会调用此方法,它允许您存储非特定于配置的项目,例如正在运行的线程。

您需要的另一件事是 AsyncTask 中的一个方法来设置它应该启用/禁用的按钮。当您的 Activity 重新启动时,您可以取消设置 Button,然后在 onCreate() 中重置它。

实现可能看起来像这样。

public class MyActivity extends Activity {
  private static final String NON_CONFIG_KEY = "com.example.NON_CONFIG_KEY";
  protected void onCreate(Bundle instanceState) {
    setContentView(R.layout.main);
    HashMap<String, Object> nonConfigState = (HashMap<String, Object>)
        getLastNonConfigurationIntstanceState();
    if (nonConfigState != null && nonConfigState.get(NON_CONFIG_KEY) != null) {
      MyAsyncTask task = (MyAsyncTask) nonConfigState.get(NON_CONFIG_KEY);
      task.setUiControl(findViewById(R.id.my_button));
    }
  }

  public Object onRetainNonConfigurationInstanceState() {
    task.setUiControl(null);
    // create HashMap, store AsyncTask in it, and return it
  }
}

public MyAsyncTask extends AsyncTask {

  private Button mControl = null;
  private boolean shouldUpdateControl = false;
  private Object mLock = new Object();

  public void setUiControl(Button b) {
    synchronized (mLock) {
      if (b != null && shouldUpdateControl) {
        b.setEnabled(true);
        shouldUpdateControl = false;
      }
      mControl = b;
    }
  }

  protected void onPostExecute(Result r) {
    synchronized (mLock) {
      if (mControl == null) {
        shouldUpdateControl = true;
      } else {
        mControl.setEnabled(true);
      }
    }
  }
}

I don't believe you need to start intercepting orientation changes. Its cutting corners and its possibly going to cause you a lot of headaches if you actually want to do things like load different resources for different orientations.

The root problem is that the reference the AsyncTask has to the button that its meant to update is stale, it refers to your old button. What you can do to solve this is implement Activity.onRetainNonConfigurationInstanceState(). This method is called in situations when an orientation change is happening and its to allow you to store items that are non-configuration specific, like running Threads.

The other thing you need is a method in your AsyncTask to set the Button it should enable/disable. While your Activity is restarting you unset the Button and then reset it in onCreate().

The implementation might looks something like this.

public class MyActivity extends Activity {
  private static final String NON_CONFIG_KEY = "com.example.NON_CONFIG_KEY";
  protected void onCreate(Bundle instanceState) {
    setContentView(R.layout.main);
    HashMap<String, Object> nonConfigState = (HashMap<String, Object>)
        getLastNonConfigurationIntstanceState();
    if (nonConfigState != null && nonConfigState.get(NON_CONFIG_KEY) != null) {
      MyAsyncTask task = (MyAsyncTask) nonConfigState.get(NON_CONFIG_KEY);
      task.setUiControl(findViewById(R.id.my_button));
    }
  }

  public Object onRetainNonConfigurationInstanceState() {
    task.setUiControl(null);
    // create HashMap, store AsyncTask in it, and return it
  }
}

public MyAsyncTask extends AsyncTask {

  private Button mControl = null;
  private boolean shouldUpdateControl = false;
  private Object mLock = new Object();

  public void setUiControl(Button b) {
    synchronized (mLock) {
      if (b != null && shouldUpdateControl) {
        b.setEnabled(true);
        shouldUpdateControl = false;
      }
      mControl = b;
    }
  }

  protected void onPostExecute(Result r) {
    synchronized (mLock) {
      if (mControl == null) {
        shouldUpdateControl = true;
      } else {
        mControl.setEnabled(true);
      }
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文