2014-09-21 56 views
1

编辑:我发现我在下面描述的只发生在我的模拟设备上(Nexus 5,目标api 19,4.4.2与Intel Atom(x86)cpu ),但不是在我的物理设备(宏达电一)...Android:暂停并恢复活动中的线程

编辑2:编辑1是由于IllegalStateException我没有捕获。添加了一些代码来检查线程是否已经运行,然后再尝试启动它。这与接受的答案相结合解决了我的问题。

我已实施启动一个新的线程在活动的onCreate方法,像这样的activty:

... 

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(); 
} 

,但我的日阅读不恢复。任何想法为什么?感谢任何帮助。

马库斯

回答

1

所有我认为答案有关于一些问题的运行变量,因为你不能写入和读取从两个不同的Threads的变量,而不synchronized block,所以我发表我自己的答案:

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必须将它们的访问。

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

+0

检查我的编辑请 – Marcus 2014-09-21 15:57:43

+0

你的代码甚至不工作。布尔值不是同步语句的有效类型的参数。 – Marcus 2014-09-21 17:13:38

+0

修复它看起来再次感谢 – mmlooloo 2014-09-21 17:17:58

0

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

Runnable work = new Runnable() { 

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

检查我的编辑请 – Marcus 2014-09-21 15:57:15

1

声明running = false;将停止Thread的执行,而不是暂停它。使用两个变量:一是停止当前Thread,另一个是暂停和继续Thread,如下:

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

在事件的活动,设置isThreadPausetrue,并在onResume事件,设置isThreadPausefalse

+0

检查我的编辑请 – Marcus 2014-09-21 15:56:32