Android 使用带片段的AsyncTask时处理配置更改

Android 使用带片段的AsyncTask时处理配置更改,android,android-fragments,android-asynctask,Android,Android Fragments,Android Asynctask,我一直在努力理解在执行后台任务时如何处理配置更改。从我的研究中,我发现最好的解决方案是将任务放在一个无头片段中,并设置setRetainInstancetrue。关于这个话题,到处都有很多讨论,例如,和,但我没有让他们中的任何一个为我工作 我试图实现的是: 将AsyncTask作为外部类放在单独的文件中。 从Headless片段内部启动AsyncTask。 显示进度对话框,而不是进度条。 将异步任务的结果返回到父活动。 我用这个做了基本相同的事情,点击按钮,它运行一些虚拟任务,并用进度条显示进度

我一直在努力理解在执行后台任务时如何处理配置更改。从我的研究中,我发现最好的解决方案是将任务放在一个无头片段中,并设置setRetainInstancetrue。关于这个话题,到处都有很多讨论,例如,和,但我没有让他们中的任何一个为我工作

我试图实现的是:

将AsyncTask作为外部类放在单独的文件中。 从Headless片段内部启动AsyncTask。 显示进度对话框,而不是进度条。 将异步任务的结果返回到父活动。 我用这个做了基本相同的事情,点击按钮,它运行一些虚拟任务,并用进度条显示进度。但是将AsyncTask作为内部类。 我尝试将Asynctask移动到外部类,但当我尝试启动后台任务时,应用程序崩溃

代码如下:

主活动父活动

 public class MainActivity extends FragmentActivity implements TaskCallbacks {
 private static final String TAG = MainActivity.class.getSimpleName();

 private static final String KEY_CURRENT_PROGRESS = "current_progress";
 private static final String KEY_PERCENT_PROGRESS = "percent_progress";

 private TaskFragment mTaskFragment;
 private ProgressBar mProgressBar;
 private TextView mPercent;
 private Button mButton;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 Log.i(TAG, "onCreate(Bundle)");
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);

// Initialize views
mProgressBar = (ProgressBar) findViewById(R.id.progress_horizontal);
mPercent = (TextView) findViewById(R.id.percent_progress);
mButton = (Button) findViewById(R.id.task_button);
mButton.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    if (mTaskFragment.isRunning()) {
      mTaskFragment.cancel();
    } else {
      mTaskFragment.start();
    }
  }
});

// Restore saved state
if (savedInstanceState != null) {
  mProgressBar.setProgress(savedInstanceState.getInt(KEY_CURRENT_PROGRESS));
  mPercent.setText(savedInstanceState.getString(KEY_PERCENT_PROGRESS));
}

FragmentManager fm = getSupportFragmentManager();
mTaskFragment = (TaskFragment) fm.findFragmentByTag("task");

// If the Fragment is non-null, then it is currently being
// retained across a configuration change.
if (mTaskFragment == null) {
  mTaskFragment = new TaskFragment();
  fm.beginTransaction().add(mTaskFragment, "task").commit();
}

if (mTaskFragment.isRunning()) {
  mButton.setText(getString(R.string.cancel));
} else {
  mButton.setText(getString(R.string.start));
}
}

@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(KEY_CURRENT_PROGRESS, mProgressBar.getProgress());
outState.putString(KEY_PERCENT_PROGRESS, mPercent.getText().toString());
}

/****************************/
/***** CALLBACK METHODS *****/
/****************************/

@Override
public void onPreExecute() {
Log.i(TAG, "onPreExecute()");
mButton.setText(getString(R.string.cancel));
Toast.makeText(this, R.string.task_started_msg, Toast.LENGTH_SHORT).show();
}

@Override
public void onProgressUpdate(int percent) {
Log.i(TAG, "onProgressUpdate(" + percent + "%)");
mProgressBar.setProgress(percent * mProgressBar.getMax() / 100);
mPercent.setText(percent + "%");
}

@Override
public void onCancelled() {
Log.i(TAG, "onCancelled()");
mButton.setText(getString(R.string.start));
mProgressBar.setProgress(0);
mPercent.setText(getString(R.string.zero_percent));
Toast.makeText(this, R.string.task_cancelled_msg, Toast.LENGTH_SHORT).show();
}

@Override
public void onPostExecute() {
Log.i(TAG, "onPostExecute()");
mButton.setText(getString(R.string.start));
mProgressBar.setProgress(mProgressBar.getMax());
mPercent.setText(getString(R.string.one_hundred_percent));
Toast.makeText(this, R.string.task_complete_msg, Toast.LENGTH_SHORT).show();
}
无头碎片


谢谢。

您需要将回调和片段传递给DummyTask

/**
* Start the background task.
*/
public void start() {
if (!mRunning) {
  mTask = new DummyTask(this, mCallbacks);
  mTask.execute();
  mRunning = true;
}
在DummyTask中添加一个构造函数

public DummyTask (TaskFragment fragment, TaskCallbacks callbacks) {
  this.framgent = fragment;
  this.callbacks = callbacks;
} 
然后你可以把 //fragment.mRunning=true;把东西放回原处,它应该像预期的那样工作


或者,您可以将DummyTask作为子类添加到TaskFragment中,并使用可访问的成员变量,然后它就可以工作了。谢谢但是在配置更改之后,进度条就挂起了。
 03-08 06:41:51.517: E/AndroidRuntime(20497): FATAL EXCEPTION: main
 03-08 06:41:51.517: E/AndroidRuntime(20497): java.lang.NullPointerException
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at com.adp.retaintask.DummyTask.onPreExecute(DummyTask.java:22)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.os.AsyncTask.execute(AsyncTask.java:534)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at com.adp.retaintask.TaskFragment.start(TaskFragment.java:73)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at com.adp.retaintask.MainActivity$1.onClick(MainActivity.java:51)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.view.View.performClick(View.java:4102)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.view.View$PerformClick.run(View.java:17085)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.os.Handler.handleCallback(Handler.java:615)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at  android.os.Handler.dispatchMessage(Handler.java:92)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.os.Looper.loop(Looper.java:155)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at android.app.ActivityThread.main(ActivityThread.java:5454)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at java.lang.reflect.Method.invokeNative(Native Method)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at java.lang.reflect.Method.invoke(Method.java:511)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at   com.android.internal.os.ZygoteInit.main(ZygoteInit.java:796)
 03-08 06:41:51.517: E/AndroidRuntime(20497):   at dalvik.system.NativeStart.main(Native Method)
/**
* Start the background task.
*/
public void start() {
if (!mRunning) {
  mTask = new DummyTask(this, mCallbacks);
  mTask.execute();
  mRunning = true;
}
public DummyTask (TaskFragment fragment, TaskCallbacks callbacks) {
  this.framgent = fragment;
  this.callbacks = callbacks;
}