【问题标题】:How to stop while loop after back button is hit按下后退按钮后如何停止while循环
【发布时间】:2015-07-19 10:21:26
【问题描述】:

我尝试了很多方法来解决我的问题,但仍然没有成功。我有一个方法,它返回一个字符串值,我正在使用它来更新我屏幕上的 TextView,如下所示: outCPU.setText(getCpuInfo());

这很好,但我需要更新这个 TextView 直到按下返回按钮。

我想我需要一个 while 循环,它在活动创建后开始,在按下后退按钮后停止。这个循环应该在一个新线程中,因为:- 我必须先加载活动并在另一个线程中执行循环,因此执行不会影响主线程和活动的加载。

正如我已经说过的,即使我花了几个小时,我也不知道如何正确地做到这一点。

有人可以告诉我一个如何完成此操作的示例吗?谢谢...!!

已编辑 - 工作中:

private Handler mHandler;
private int i;


@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_systeminfo);

    outCPU = (TextView) findViewById(R.id.outCPU);
    outMEM = (TextView) findViewById(R.id.outMEM);
    outTASKS = (TextView) findViewById(R.id.outTASKS);

    i = 0;
    mHandler = new Handler();
    mHandler.post(mUpdate);

}


private Runnable mUpdate = new Runnable() {
    @Override
    public void run() {
        outCPU.setText(getCpuInfo());
        outMEM.setText(getMemInfo());
        outTASKS.setText(getTasksInfo());
        i++;
        mHandler.postDelayed(this, 1000);
    }
};

@Override
public void onBackPressed() {

    mHandler.removeCallbacks(mUpdate);
    super.onBackPressed();
    Log.i("MSG", "Going back");

    finish();

}

【问题讨论】:

  • 能否贴出包含循环的代码
  • 也许我很笨,但是为什么你有两个嵌套线程?
  • @andrew 检查我的答案
  • @JonasCz 我不太了解,但我认为它的工作原理是这样的:我需要创建一个与主线程分开运行的线程,否则它会卡在一个循环中并且没有加载活动一切都变糟了……在那个线程中我也无法对 UI 进行任何更改,所以这就是为什么存在 runOnUiThread ..

标签: java android multithreading loops while-loop


【解决方案1】:

在您的应用中的某处使用共享标志:

private volatile boolean wasPressed = false;

在while循环中,检查这个标志:

while (!wasPressed) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            outCPU.setText(getCpuInfo()); 
        }
    });
    // sleep for a while
}

在按钮点击监听器上,将wasPressed 切换为true

【讨论】:

  • 这种方式行不通,我黑屏了,我认为是因为while循环在执行时阻塞了onCreate方法..
  • “我需要一个 while 循环,它在活动创建后开始,在按下后退按钮后停止。这个循环应该在一个新线程中”
  • 在代码中,您作为问题更新发布,我看到了新线程的创建,但不是启动
  • 并在while循环中添加一些延迟(例如Thread.sleep(200)),否则您的智能手机会变成烤架))
【解决方案2】:

您可以在线程中使用AsyncTask 对UI 线程执行操作。或者你可以使用 'my favorite' ,ThreadHandler 的组合。为了确保按下返回时线程停止,您可以使用handler.removeCallBacks(Runnable) 以下示例可以解决您的问题:

//Global
Handler h = new Handler();

private static boolean flag = true;

public void updateTextView(){

 // call thread here
 h.post(thread);
}


  // take this thread out side so that it can be stopped with handler
 Thread thread = new Thread(){

 public void run(){

      while(flag)
      outCPU.setText(getCpuInfo());

    }

 }

public void onBackPressed(){

    flag = false;
    h.removeCallBacks(thread);
    super.onBackPressed();

}

【讨论】:

  • @SashaSalauyou 我知道,我正在使用Handler 在 UI 线程和我的其他线程之间进行通信。欲了解更多信息,请阅读official docs
  • 不起作用,它卡在 while 循环中,所以活动都没有加载,只是黑屏
  • 我有一个 asynctask 的解决方案,但我没有找到如何在其上应用循环的方法,有没有办法可以将 doInBackground 方法放入循环中?
  • @andrew 看着你的代码,我不明白你为什么要使用嵌套的Thread ??我自己测试过这个场景,它工作得很好。您不能在循环中调用doInBackground() ......当然也不能从doInBackground 更新用户界面......你必须在你的情况下使用我上面的例子。使用HandlerThread。并删除嵌套的 Thread
  • 抱歉,您能解释一下“嵌套”线程的确切含义吗?我对我的代码做了一些更改,现在它正在工作。但是仍然遇到一个问题,如果我运行此代码,如您在页面顶部看到的那样,android studio 告诉我,它的主线程工作量太大,我想我可以通过使用new Asynctask.execute() 来解决这个问题做我的工作来获取 CPU 值,但是当我离开这个活动然后返回时,通过 asyncask 显示一些值需要太多时间......你不知道这是为什么吗?
猜你喜欢
  • 1970-01-01
  • 2020-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多