2017-05-16 93 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; 
    }