문제

Hey everyone I am fairly new to the android/glass development so please correct me if I am wrong.

I tried to create a High Frequency Live Card which is fine. However when I close the app, the function surfaceDestroyed() did not get trigger and thread.quit() did not get called.

I tried looking into the sample project stopwatch/timer and apparently they did not stop the thread as well. According to the documentation, surfaceDestroyed gets called right before the surface is destroy but what is my surface? I also read something call surfaceview, are they the same thing? is surfaceview my customview or livecard?

https://developers.google.com/glass/develop/gdk/ui/live-cards#creating_high-frequency_live_cards

Appreciate any kind of help!!!

/ ***
  * LiveCardRender Class
*** /
public class LiveCardRender implements DirectRenderingCallback {
    private static final long FRAME_TIME_MILLIS = 33;
    private CustomView mCustomView;
    private SurfaceHolder mHolder;
    private boolean mPaused;
    private RenderThread mRenderThread;

    private class RenderThread extends Thread {
        private boolean mShouldRun;

        public RenderThread() {
            mShouldRun = true;
        }

        private synchronized boolean shouldRun() {
            return mShouldRun;
        }

        public synchronized void quit() {
            mShouldRun = false;
        }

        @Override
        public void run() {
            while (shouldRun()) {
                draw(mCustomView);
                SystemClock.sleep(FRAME_TIME_MILLIS);
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mHolder = holder;
        updateRendering();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mHolder = null;
        updateRendering();
    }

    @Override
    public void renderingPaused(SurfaceHolder holder, boolean paused) {
        mPaused = paused;
        updateRendering();
    }

    private synchronized void updateRendering() {

        boolean shouldRender = (mHolder != null) && !mPaused;
        boolean rendering = mRenderThread != null;

        if (shouldRender != rendering) {
            if (shouldRender) {
                mRenderThread = new RenderThread();
                mRenderThread.start();
            } else {
                mRenderThread.quit();
                mRenderThread = null;
            }
        }
    }

    private void draw(View view) {

        Canvas canvas;
        try {
            canvas = mHolder.lockCanvas();
        } catch (Exception e) {
            return;
        }
        if (canvas != null) {
            view.draw(canvas);
            mHolder.unlockCanvasAndPost(canvas);
        }
    }
}

/ ***
  * LaunchService Class that uses LiveCardRender to update the live card
*** /
public class LaunchService extends Service {
    private static final String LIVE_CARD_TAG = "motion_card";
    private TimelineManager mTimelineManager;
    private LiveCard mLiveCard;
    private LiveCardRender mLiveCardRender;

    @Override
    public void onCreate() {
        mTimelineManager = TimelineManager.from(this);
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mLiveCard == null) {
            mLiveCard = mTimelineManager.createLiveCard(LIVE_CARD_TAG);
            mLiveCardRender = new LiveCardRender(this);
            mLiveCard.setDirectRenderingEnabled(true);
            mLiveCard.getSurfaceHolder().addCallback(mLiveCardRender);
            mLiveCard.publish(PublishMode.REVEAL);
        }
        return START_STICKY;
    }

    @Override
    public void onDestroy(){
        if (mLiveCard != null && mLiveCard.isPublished()) {
            if (mLiveCardRender != null) {
                mLiveCard.getSurfaceHolder().removeCallback(mLiveCardRender);
            }
            mLiveCard.unpublish();
            mLiveCard = null;
        }
        super.onDestroy();
    }
}
도움이 되었습니까?

해결책

It looks like the bug is here, inside onDestroy:

if (mLiveCard != null && mLiveCard.isPublished()) {
    if (mLiveCardRender != null) {
        mLiveCard.getSurfaceHolder().removeCallback(mLiveCardRender);
    }
    mLiveCard.unpublish();

By removing the callback before the unpublish method is called, the system no longer knows whose surfaceDestroyed method to call when the card is removed afterwards. You can actually remove call to removeCallback entirely; it's unnecessary.

It looks like this is a bug in some of our samples that we missed as our APIs evolved. Thanks for catching it and we'll have them updated shortly!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top