【问题标题】:Android/Glass: How to trigger surfaceDestroyedAndroid/Glass:如何触发surfaceDestroyed
【发布时间】:2014-01-22 15:20:40
【问题描述】:

大家好,我是 android/glass 开发的新手,如果我错了,请纠正我。

我尝试创建一个高频 Live Card,这很好。但是,当我关闭应用程序时,函数 surfaceDestroyed() 没有被触发并且 thread.quit() 没有被调用。

我尝试查看示例项目秒表/计时器,显然他们也没有停止线程。根据文档,surfaceDestroyed 在表面被破坏之前被调用,但我的表面是什么?我还读了一些叫做surfaceview的东西,它们是一样的吗? surfaceview 是我的 customview 还是 livecard?

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

感谢任何形式的帮助!!!

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

【问题讨论】:

  • 如何关闭您的应用程序?当 LiveCard 未发布时,样本的渲染线程确实会被终止:这只发生在服务停止时。
  • 我的没有。例如谷歌秒表示例,我在绘图(查看视图)函数中放置了一条日志消息,即使在我使用菜单选项“停止”关闭应用程序之后也是如此。 Log 消息在 LogCat 中继续运行。而且 surfaceDestroyed(SurfaceHolder holder) 中的日志消息永远不会被调用
  • 嗯,这似乎是一个错误...您可以停止渲染线程的另一种方法是在调用 Service 的 onDestroyed 方法时手动调用 onSurfaceDestroyed

标签: android multithreading surfaceview google-glass surfaceholder


【解决方案1】:

看起来 bug 就在这里,在 onDestroy 内部:

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

通过在调用unpublish方法之前移除回调,系统不再知道在之后移除卡片时调用谁的surfaceDestroyed方法。您实际上可以完全删除对removeCallback 的调用;这是不必要的。

看起来这是我们的一些示例中的一个错误,我们在 API 发展过程中遗漏了这些错误。感谢您的关注,我们会尽快更新!

【讨论】:

  • 太棒了!玻璃队加油!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多