1

I have a problem with my onCreate method. I have identified that when I switch to this activity the onCreate method gets called twice and therefore starting 2 threads which I dont want. Because the thread sends coordinates to a RaspberryPi and the 2nd unwanted thread always sends 0 0 0 which I dont want. I cant seem to find a fix for this so . . . I'd appreciate help if someone could tell me a fix so the thread starts only once.

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

EDIT: I tried something with 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);
}

what this does is weird. Now I only have one thread that crashes immediately after sending the coordinates once.

Logs:

Log.i that i put before sending:

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

Log that comes right after

I/System: core_booster, getBoosterConfig = false

Edit 2:

I've also tried starting the thread at an other timing. In my onTouch like this:

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
}

But this results into the same as my try with SaveInstanceState a thread that transmits once but doesnt loop.

Edit 3: I should probably post my thread too

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

FINAL EDIT:

I managed to do a workaround. I check before sending if the value is 0 if it is then I change it to 200. On the other end I check if its 200 and change it to 0 and ignore any 0 that I get.

Slimestone
  • 11
  • 2

4 Answers4

0

First of all OnCreate will only be called one time for each lifetime of the Activity. However, there are a number of situations that can cause your activity to be killed and brought back to life. Thus, OnCreate get called again.

First thing you can debug the code and find the place where it called repeatedly.

Note: To avoid this situation you can save state information in onSaveInstanceState and restore it back in the state bundle you get in on create.

Thanks

Rameshbabu
  • 611
  • 2
  • 7
  • 21
  • You are wrong- onCreate is supposed to be called once, but creating thread inside it making it getting called again- http://stackoverflow.com/a/22224038/4810277 – X3Btel May 16 '17 at 13:45
  • Ok i agree with your message. Am just telling the Activity life cycle. We can able to call the same activity many times. But we need to debug the multiple calls by our self. – Rameshbabu May 16 '17 at 13:54
0

OnCreate() already creates a main thread, and then you call another instance of the main class by manually creating a thread of the main class.

AppWriter
  • 247
  • 2
  • 13
0

According to this answer all you dont need boolean check, just check if savedInstance is null, and only then start the second thread.

More general solution would be to initialise and start the thread in onStart() but dont forget to stop it in onStop() . If you want this thread to be long running in the background- I suggest start using something else- Service docs

Community
  • 1
  • 1
X3Btel
  • 1,408
  • 1
  • 13
  • 21
0

Any configuration change will cause Android to restart your Activity like screen rotation, keyboard availability etc. what the system is actually doing is calling onDestroy() and then immediately calling onCreate(), meaning that the original Activity object is replaced by a new one without any knowledge of the executing background thread, so only the Activity object that started the thread knows that the thread was started.

A better way of handling this is through retaining thread in Activity.

The Activity class contains two methods for handling thread retention:

public Object onRetainNonConfigurationInstance()

called before configuration change occurs

public Object getLastNonConfigurationInstance()

Called in the new Activity object to retrieve the retained object returned in onRetainNonConfigurationInstance()

So you can implement this in following way.

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;
    }
Fahadsk
  • 1,099
  • 10
  • 24