简体   繁体   中英

Android activity with threads get destroyed after onStop()

So I have an activity for a game which holds two extra threads for updating and rendering. When I press home (or hide activity in any other means) and return, the screen freezes for some time and the activity restarts like with the last intent. This especially happens often when I long press home (enter running apps list). I assume the problem lies in threads handling here.

Also LogCat: 07-01 16:52:28.793 28502-28603/com.example.game A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x7f95401a20 in tid 28603 (Thread-5887)

Surely, I can store failsafe data with onSave/RestoreInstanceState, but still the freeze occurs and that segfault looks a bit disturbing.

public class GameActivity extends AppCompatActivity {
    private Thread renderThread,updateThread;
    private boolean ActivityHidden=false,Pause=false,Alive=true;
    private int renderSleep=25;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //Constructing stuffs
        renderThread = new Thread(renderRunanble);
        updateThread = new Thread(updateRunnable);
    }

    public void render(){
        if(ActivityHidden) return;
        //Rendering...
    }

    protected void onPause(){
        super.onPause();
        Paused=true;
    }

    protected void onResume(){
        super.onResume();
        if(!renderThread.isAlive()) renderThread.start();
        if(!updateThread.isAlive()) updateThread.start();
    }

    protected void onStop() {
        super.onStop();
        ActivityHidden=true;
        renderSleep=250;
    }

    protected void onStart() {
        super.onStart();
        ActivityHidden=false;
        renderSleep=25;
    }

    protected void onDestroy() {
        super.onDestroy();
        Alive=false;
        try {renderThread.join();} catch(Exception e) {}
    }

    private Runnable renderRunnable = new Runnable() {
        public void run() {
            while(Alive) {
                render();
                try {Thread.sleep(renderSleep);} catch(Exception e){}
            }
        }
    };

    private Runnable updateRunnable = new Runnable() {
        public void run() {
            while(Alive) {
                if(!Paused)
                //updates happening
                try {Thread.sleep(25);} catch(Exception e){}
            }
        }
    };
}

@edit: Note - I cannot reproduce it on emulator with API 16 nor 21. It happens on my physical device with API 22.

I'm not sure 100% if I just found the solution but after applying this and trying a lot to crash the app, I didn't encounter segfault. After onStop() I interrupt threads, join the render thread and nullify them. onStart() I create new threads basing on runnables.

protected void onStop() {
    ActivityHidden=true;
    Alive=false;
    renderSleep=250;
    updateThread.interrupt();
    renderThread.interrupt(); //Sometimes don't happen because it's still rendering
    try {renderThread.join();} catch(Exception e){}
    updateThread=null;
    renderThread=null;
    super.onStop();
}

protected void onStart() {
    super.onStart();
    ActivityHidden=false;
    Alive=true;
    renderSleep=25;
    if(updateThread==null) {updateThread = new Thread(updateRunnable); updateThread.start();}
    if(renderThread==null) {renderThread = new Thread(renderRunnable); renderThread.start();}
}

Surely, here if the app is extremely fast switched between onStop and onStart the method might fail, but this in practice shouldn't happen. And still there's no guarantee that there will be no duplicates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM