2017-05-16 57 views
1

我的onCreate方法有问题。我已经确定,当我切换到这个活动时,onCreate方法被调用两次,因此启动2个我不想要的线程。因为线程向RaspberryPi发送坐标,第二个不需要的线程总是发送0 0 0,我不想要。我似乎无法找到这样的解决办法。 。 。如果有人能告诉我一个修补程序,我会很感激帮助,因此线程只启动一次。线程启动两次

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

     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

     Joystick = (ImageView) findViewById(R.id.Joystick); 
     Regler = (ImageView) findViewById(R.id.Regler); 
     buttonFoto = (Button) findViewById(R.id.buttonFoto); 
     buttonVideo = (Button) findViewById(R.id.buttonVideo); 
     buttonNeu = (Button) findViewById(R.id.buttonNeu); 
     buttonSpeichern = (Button) findViewById(R.id.buttonSpeichern); 

     touchscreenJoystick = (TextView) findViewById(R.id.touchscreenJoystick); 
     touchscreenJoystick.setOnTouchListener(this); 
     touchscreenRegler = (TextView) findViewById(R.id.touchscreenRegler); 
     touchscreenRegler.setOnTouchListener(this); 

     RL = (RelativeLayout) findViewById(R.id.activity_main); 
     running = true; 
     firstTouch = true; 

     Bild = (WebView) findViewById(R.id.webView); 
     Bild.loadUrl("http://10.0.0.1:8080/stream"); 

     thread = new Thread(new MainActivity.TransmitThread()); 
     thread.start(); 
    } 

编辑: 我尝试一些与SaveInstanceState

//Same onCreate-stuff as above 
    if(savedInstanceState == null) 
    { 
     thread = new Thread(new MainActivity.TransmitThread()); 
     thread.start(); 
    } 

} 

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    outState.putString("message","crashed"); 
    super.onSaveInstanceState(outState); 
} 

这样做是什么奇怪的。现在我只有一个线程在发送坐标后立即崩溃。

日志:

Log.i我在发送之前提出:

我有:自带之后

I/System: core_booster, getBoosterConfig = false 

编辑2

I/sent: //X: 0 //Y: 0 //Z: 0 

登录也尝试在另一个时间启动线程。在我onTouch这样的:

public boolean onTouch(View v, MotionEvent me) 
{ 
    xt = me.getX(); 
    yt = me.getY(); 
    int Aktion = me.getAction(); 

    if(firstTouch) 
    { 

     thread = new Thread(new MainActivity.TransmitThread()); 
     thread.start(); 

     firstTouch = false; 
    } 
    //other stuff that i need to do here 
} 

但是这会导致在同一个作为我尝试用SaveInstanceState发送一次,但犯规循环的线程。

编辑3: 我应该张贴我的线程也

class TransmitThread implements Runnable 
{ 
    @Override 
    public void run() 
    { 
     while(running) 
     { 
      delay();  
      xss = xs;  
      yss = ys; 
      zss = zs; 
      Log.i("sent","//X: " + xss + " //Y: " + yss + " //Z: " + zss); 
      transmit();  
     } 
    } 

    public void transmit() 
    { 
     try{ 
      socket = new Socket(ServerIP,ServerPort); 

      OutputStream outputStream = socket.getOutputStream(); 
      PrintStream printStream = new PrintStream(outputStream); 

      BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); 

      printStream.print(xs + " " + ys + " " + zs); 
      Akkustand = input.readLine(); 

      handler.sendEmptyMessage(0); 

     }catch(UnknownHostException e){ 
      e.printStackTrace(); 
     }catch(IOException e){ 
      e.printStackTrace(); 
     } 
    } 

    public void delay(){ 
     try { 
      Thread.sleep(200); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

最后编辑:

我设法做一个变通方法。我发送前检查,如果值是0,如果它是然后我将它更改为200.另一方面,我检查是否它的200并将其更改为0并忽略我得到的任何0。

+1

使用布尔标志 –

+0

@Slimestone尝试调试您的代码并找到它。这很简单。您甚至可以检查该变量是否包含0,并在发送之前避免它。 – RameshJaga

+0

你最终可以使用'thread.isAlive()'https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#isAlive(),但你必须检查'线程! = null' –

回答

0

首先OnCreate将只在活动的每个生命周期中被调用一次。但是,有很多情况会导致您的活动被杀死并重新启用。因此,OnCreate再次被调用。

首先,您可以调试代码并找到重复调用的位置。

注意:为避免出现这种情况,您可以将状态信息保存在onSaveInstanceState中,并将其恢复到您在创建时所处的状态包中。

感谢

+0

你错了 - onCreate应该被调用一次,但是在它内部创建线程使其再次被调用 - http:// stackoverflow.com/a/22224038/4810277 – X3Btel

+0

好吧,我同意你的信息。我只是告诉活动的生命周期。我们可以多次致电相同的活动。但是我们需要通过我们自己调试多个调用。 – RameshJaga

+0

调试器启动线程后崩溃 – Slimestone

0

的OnCreate()已经创建了一个主线程,然后通过手动创建主类的线程中调用主类的另一个实例。

0

根据this回答所有你不需要布尔检查,只检查savedInstance是否为空,然后才开始第二个线程。

更一般的解决方案是初始化并启动onStart()中的线程,但不要忘记在onStop()中停止它。如果你想让这个线程在后台长时间运行 - 我建议开始使用其他的东西 - 我建议开始使用其他的东西 - Service docs

+0

我不想要第二个线程 – Slimestone

0

任何配置更改将导致Android重新启动您的活动,如屏幕旋转,键盘可用性等系统实际上在做什么调用onDestroy(),然后立即调用onCreate(),这意味着原来的Activity对象被一个新的替换为一个没有任何执行后台线程的知识,所以只有启动该线程的Activity对象知道该线程已启动。

处理此问题的更好方法是在Activity中保留线程。

Activity类包含了处理线程保留两种方法:

public Object onRetainNonConfigurationInstance() 

配置更改之前调用发生

public Object getLastNonConfigurationInstance() 

在新的活动对象调用来检索保留对象onRetainNonConfigurationInstance()

返回

所以你可以通过以下方式来实现它。

private static MyThread t; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     Object retainedObject = getLastNonConfigurationInstance(); 
     if (retainedObject != null) { 
      t = (MyThread) retainedObject; 
     } 
     else{ 
      t = new MyThread(); 
      t.start(); 
     } 
    } 

    @Override 
    public Object onRetainNonConfigurationInstance() { 
     if (t != null && t.isAlive()) { 
      return t; 
     } 
     return null; 
    }