退出ASyncTasks时Android主线程停止

时间:2017-04-01 21:45:52

标签: java android multithreading android-asynctask

我目前正试图弄清楚如何在退出ASyncTasks时避免主线程中的停顿,并且我将尝试用特定问题的框架代码进行解释。对不起,如果这是重复的话,除了有关ASyncTasks在执行期间停止主线程的帖子之外,我还没有看到任何其他内容。我有一个假设是什么引起了这个问题,但我不知道它是否正确。如果它是对的,或者它是错的,我想知道"正确的"处理这种情况的方法。

public class AST extends ASyncTask<String, Integer, Void> {
  private Activity mActivity;
  private interfaceObject mInterface;

  public AST(Activity activity, interfaceObject interface) {
    mActivity = activity;
    mInterface = interface;
  }

  @Override
  protected void onPreExecute() {
    //mInterface.setStatus("Starting...");
    mInterface.setStatus("Doing Stuff...");
  }

  @Override
  protected String doInBackground(Void... params) {
    String string = doStuff();

    //mInterface.setStatus("Did Stuff."); As mentioned this shouldn't be done.

    return string;
  }

  @Override
  protected void onProgressUpdate(Integer... progress) {
    //mInterface.setStatus("Doing Stuff...");
    mInterface.progressUpdate(progress[0], progress[1]);
  }

  @Override
  protected void onPostExecute(String result) {
    mInterface.setStatus("Finished.");
    mInterface.astDone(result);
  }

  private String doStuff() {
    StringBuilder string = "";
    for(int i=0; i<10000; i++) {
      string.append("A");
      publishProgress(i, 10000);
    }
    return string.toString();
  }
}

具体来说,setStatus(String status)编辑主线程上textView的文本。 progressUpdate(int progress,int max)对进度条执行相同的操作。在大约90%时,进度条会冻结整个UI(尽管Log.d输出正确的值)。消息&#34; Do Stuff。&#34;永远不会出现,并且随着字符串变大,有大约200个跳过的帧会变大。在200个跳过的帧之后,&#34;完成。&#34;出现并调用astDone(启动另一个ASyncTask)。

现在为什么会这样?

我的理论是,当主线程必须读入大字符串时,它会停止,但我不知道我是否会基于此而离开?是否有适当的&#34;将大数据从一个ASyncTask传递到另一个ASyncTask的方法?我想我可以在一个文件中写入一个文件并在另一个文件中从中读取文件,但这是否被认为是正确的?

感谢您的时间!

另外,作为一个旁听的问题,如果我放慢doStuff()方法的速度,通过添加一个额外的循环,进度条将使其达到100%并且&#34;完成。&#34;确实出现了。在我的大字符串停止之前,主线程是否总是不会收到这些?主线程没有订单处理程序,所以我觉得我的publishProgress调用需要花费的时间长于实际显示进度的主线程吗?我只是不明白主线程如何在ASyncTask对主线程的调用中的不同点停顿。主线程是否应该在收到ASyncTask时执行调用,然后点击变量read并停止?

Edit1:我已经更改了代码以匹配Melquiades的建议,不幸的是我还在跳过200帧。

Edit2:由于它即将发布,我将包含setStatus和progressUpdate的代码:

@Override
public void progressUpdate(int cur, int max) {
    progressBar.setMax(max);
    progressBar.setProgress(cur);
}

@Override
public void setStatus(String status) {
    statusBar.setText(status);
}

progressBar和statusBar都是在onCreate()上初始化的成员变量,虽然现在看起来他们可能没有必要这样做。这是错的吗?

private ProgressBar progressBar;
private TextView statusBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    statusBar = (TextView) findViewById(R.id.textView);
    progressBar = (ProgressBar) findViewById(R.id.progressBar);
}

Edit3:按照建议将setStatus()移出onProgressUpdate()。

1 个答案:

答案 0 :(得分:0)

  

setStatus(String status)编辑主线程上textView的文本。

你如何准确地做到这一点(如果使用这种方法,身体是什么?)请记住,在AsyncTask中,应该尝试从doInBackground()访问UI元素 - 此方法不在UI线程上运行,而是与其他3个回调(onPreExecuteonPublishProgressonPostExecute)相反。

另一件事 - 这条无辜的路线:

string += "A"; 

实际创建新字符串10k次,Stringsimmutable

要尝试的事情:

  • 了解在setStatus
  • 中发表评论doInBackground()时会发生什么情况
  • doStuff()方法
  • 中使用StringBuilder而不是String