Android:暂停并恢复活动中的某个主题

时间:2014-09-21 13:58:13

标签: android multithreading android-activity

编辑:我发现我在下面描述的内容只出现在我的模拟设备上(Nexus 5,目标api 19,4.4.2带有Intel Atom(x86)cpu),但不在我的物理设备上(HTC)一)....

EDIT2:Edit1是由于我没有抓到的IllegalStateException。在尝试启动之前添加了一些代码来检查线程是否已经运行。结合已接受的答案解决了我的问题。

我已经实现了一个在activity的onCreate方法中启动一个新线程的激活,如下所示:

...

private boolean running;

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

    running = true;
    new Thread(null, work, "myThread").start();
}

Runnable work = new Runnable() {

    @Override
    public void run() { 
        while (running) {
            //Doing work
        }
    }
};

我正在用我的活动的onPause方法“暂停”我的帖子,如下所示:

@Override
protected void onPause() {
    running = false;
    super.onPause();
}

所以我认为恢复它会同样容易......¨

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

但我的线程没有恢复。有什么想法吗?感谢任何帮助。

马库斯

3 个答案:

答案 0 :(得分:2)

我认为所有答案都有关于运行变量的一些问题,因为无法在没有Threads <的情况下从两个不同的synchronized block写入和读取变量/ strong>所以我发表自己的答案:

package com.example.threadandtoast;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {
    public class MonitorObject{
           public boolean running = true;
           public String message = "";
           public boolean mustBePost = true;
    }

    Thread t;
    int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted 
                               // when i pause, you can see it and track it in DDMS

    Runnable work = new Runnable() {
        boolean myRunning;
        @Override
        public void run() {
            synchronized(mSync) {
               myRunning = mSync.running;
            }
            while (myRunning) {
                runOnUiThread(new Runnable() {  // in order to update the UI (create Toast)
                @Override                       // we must switch to main thread
                public void run() { 
                    // i want to read the message so i must use synchronized block
                    synchronized(mSync) { 
                    // i use this variable to post a message just for one time because i am in an infinite loop
                    // if i do not set a limit on the toast i create it infinite times 
                      if(mSync.mustBePost){       
                          Toast.makeText(MainActivity.this, mSync.message, Toast.LENGTH_SHORT).show();
                          // the message post so i must set it to false
                          mSync.mustBePost = false;
                          // if i am going to pause set mSync.running to false so at the end of infinite loop 
                          //of thread he reads it and leaves the loop
                          if(mSync.message.equals("Main Activity is going to pause")){
                              mSync.running=false;            
                          }
                      }
                    }
                }
               });

            synchronized(mSync) {
               myRunning = mSync.running;
           }
         }
       }
    };

    final MonitorObject mSync = new MonitorObject();

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    @Override
    protected void onPause() {
        super.onPause();
        synchronized(mSync) {
            // mSync.running = false; you can not set it here because 
            // it is possible for the thread to read it and exit the loop before he posts your message
            mSync.mustBePost=true;
            mSync.message = "Main Activity is going to pause";
        }    
    }

    @Override
    protected void onResume(){
       super.onResume();
       threadNameCounter++;
       synchronized(mSync) {
            mSync.running = true;
            mSync.mustBePost=true;
            mSync.message = "Main Activity is going to resume";
        } 
       t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
       t.start();
    }

}

或者您可以使用此代码:

public class MainActivity extends ActionBarActivity {

    Thread t;
    int threadNameCounter = 0; // i use this variable to make sure that old thread is deleted 
                               // when i pause, you can see it in DDMS

    String message = "";
    boolean isPost = false;

    Runnable work = new Runnable() {

        @Override
        public void run() {

            while (true) {
                runOnUiThread(new Runnable() {  
                @Override                       
                public void run() { 
                    if(!isPost){
                        Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
                        isPost = true;
                        if( message.equals("Main Activity is going to pause")){
                            t.interrupt();
                        }

                    }
                }
               });
           if(Thread.currentThread().isInterrupted()){
               break;
           } 
         }
       }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    @Override
    protected void onPause() {
        super.onPause();
        message = "Main Activity is going to pause";
        isPost = false;
    }

    @Override
    protected void onResume(){
       super.onResume();
       message = "Main Activity is going to resume";
       isPost = false;
       threadNameCounter++;
       t = new Thread(work,"My Name is " + String.valueOf(threadNameCounter));
       t.start();
    }

}

您也可以使用信号量或等待通知方法。

我将public String message = "";public boolean mustBePost = true;放入mSync对象,但确实如此 没有必要,因为只有main thread才能访问它们。

如果您有任何问题,请询问。

答案 1 :(得分:1)

语句running = false;将停止执行Thread,而不是暂停它。使用两个变量:一个用于停止当前Thread,另一个用于暂停和恢复Thread,如下所示:

boolean isThreadPause=false;
Runnable work = new Runnable() {    
    @Override
    public void run() { 
        while (running) {
            if (!isThreadPause) {
               // Doing work
            }
        }
    }
};

在活动的onPause事件中,将isThreadPause设置为true,并在onResume事件中将isThreadPause设置为false

答案 2 :(得分:0)

这是因为Runnable循环在while循环停止时停止。你可以试试这个:

Runnable work = new Runnable() {

    @Override
    public void run() { 
        while () {
          if(running){
            //Doing work
          }
        }
    }
};