2012-04-30 65 views
2

我花了很多小时寻找解决方案,需要帮助。Android屏幕旋转后从嵌套的AsyncTask onPostExecute保存数据

我在我的Android应用程序Activity中嵌套了AsyncTask,我希望允许用户在处理期间旋转他的手机,而无需启动新的AsyncTask。我试图使用onRetainNonConfigurationInstance()和getLastNonConfigurationInstance()。

我能够保留任务;但是在旋转后,它不会将onPostExecute()的结果保存到外部类变量中。当然,我尝试过getter和setter。当我将这个变量转储到onPostExecute时,它是可以的。但是,当我尝试从onClick监听器访问变量时,它是空的。

也许代码会让问题变得清晰。

public class MainActivity extends BaseActivity { 

    private String possibleResults = null; 
    private Object task = null; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      this.task = getLastNonConfigurationInstance(); 

      setContentView(R.layout.menu); 

      if ((savedInstanceState != null) 
          && (savedInstanceState.containsKey("possibleResults"))) { 
        this.possibleResults = savedInstanceState 
            .getString("possibleResults"); 
      } 

      if (this.possibleResults == null) { 
        if (this.task != null) { 
          if (this.task instanceof PossibleResultWebService) { 
            ((PossibleResultWebService) this.task).attach(); 
          } 

        } else { 
          this.task = new PossibleResultWebService(); 
          ((PossibleResultWebService) this.task).execute(this.matchToken); 
        } 
      } 

      Button button; 
      button = (Button) findViewById(R.id.menu_resultButton); 
      button.setOnClickListener(resultListener); 
    } 

    @Override 
    protected void onResume() { 
      super.onResume(); 
    } 

    OnClickListener resultListener = new OnClickListener() { 
      @Override 
      public void onClick(View v) { 

        Spinner s = (Spinner) findViewById(R.id.menu_heatSpinner); 
        int heatNo = s.getSelectedItemPosition() + 1; 
        Intent myIntent = new Intent(MainActivity.this, 
            ResultActivity.class); 
        myIntent.putExtra("matchToken", MainActivity.this.matchToken); 
        myIntent.putExtra("heatNo", String.valueOf(heatNo)); 
        myIntent.putExtra("possibleResults", 
            MainActivity.this.possibleResults); 

        MainActivity.this.startActivityForResult(myIntent, ADD_RESULT); 
      } 
    }; 

    private class PossibleResultWebService extends AsyncTask<String, Integer, Integer> { 

      private ProgressDialog pd; 
      private InputStream is; 
      private boolean finished = false; 
      private String possibleResults = null; 

      public boolean isFinished() { 
        return finished; 
      } 

      public String getPossibleResults() { 
        return possibleResults; 
      } 

      @Override 
      protected Integer doInBackground(String... params) { 
       // quite long code 
      } 

      public void attach() { 
        if (this.finished == false) { 
          pd = ProgressDialog.show(MainActivity.this, "Please wait...", 
              "Loading data...", true, false); 
        } 
      } 

      public void detach() { 
        pd.dismiss(); 
      } 

      @Override 
      protected void onPreExecute() { 
        pd = ProgressDialog.show(MainActivity.this, "Please wait...", 
            "Loading data...", true, false); 
      } 

      @Override 
      protected void onPostExecute(Integer result) { 
        possibleResults = convertStreamToString(is); 
        MainActivity.this.possibleResults = possibleResults; 

        pd.dismiss(); 
        this.finished = true; 
      } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 

      super.onSaveInstanceState(outState); 

      if (this.possibleResults != null) { 
        outState.putString("possibleResults", this.possibleResults); 
      } 

    } 

    @Override 
    public Object onRetainNonConfigurationInstance() { 
      if (this.task instanceof PossibleResultWebService) { 
        ((PossibleResultWebService) this.task).detach(); 
      } 
      return (this.task); 
    } 

}

+0

考虑将你的asynctask投入使用。然后,这个活动将开始提取数据并将其存储在内存中的服务。当活动再次询问相同的数据时,服务可以提供存储的数据。 –

回答

0

这是因为你创建每个实例化的活动时间(所以每次你得到一个新的,新的,OuterClass.this参考)的OnClickListener,但是你保存的AsyncTask在Activity实例之间,并通过引用OuterClass.this来保持对第一个实例化Activity的引用。

有关如何做到这一点右边的内容,请参阅https://github.com/commonsguy/cw-android/tree/master/Rotation/RotationAsync/

你会看到他有一个连接()和分离在他RotationAwareTask()方法来解决这个问题。

要确认AsyncTask中的OuterClass.this引用将始终指向第一个实例化的Activity,如果将其保持在屏幕方向更改之间(使用onRetainNonConfigurationInstance),则可以使用静态计数器,每次使用默认值增加默认值构造函数并保留一个实例级变量,该变量在每次创建时都被设置为count,然后将其打印出来。

+0

非常感谢,我管理它! – JCZ