I created a toy app that demos my problem ... the complete code can be
found here:  http://www.smileproject.com/SurfCodeExample.zip

Feedback super appreciated.  Here is the code from the activity and
view only ...

public class Surf extends Activity {
    /** Called when the activity is first created. */
        
    private SurfView mView;     
    private SurfThread mThread;

        private static final int COLOR_MENU_ID = Menu.FIRST;
        public static final int ACTIVITY_ASSIGN_COLOR = 0;
        
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        mView= new SurfView(this, null);
        setContentView(mView);
   }

        @Override
        protected void onPause() {
                // TODO Auto-generated method stub
                super.onPause();
                
                System.out.println ("PAUSED");
                mThread.pause();
        }

        @Override
        protected void onResume() {
                // TODO Auto-generated method stub
                super.onResume();
                
                System.out.println ("RESUMED");

                mThread = mView.getThread();
            mThread.resume();
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                
                boolean result = super.onCreateOptionsMenu(menu);
                
                menu.add(0, COLOR_MENU_ID, 0, R.string.menu_color);
                
                return result;
        }

        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
                super.onPrepareOptionsMenu(menu);
                return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

                super.onOptionsItemSelected(item);

                switch (item.getItemId()) {

                case COLOR_MENU_ID:
                        Intent i = new Intent(this, SurfChooser.class);
                        startActivityForResult(i, ACTIVITY_ASSIGN_COLOR);
                        return true;
                }
                
                return true;
        }       

         @Override
         protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
                // TODO Auto-generated method stub
                super.onActivityResult(requestCode, resultCode, data);

                Bundle extras;
                
                if (data == null) return;
                
                extras = data.getExtras();

                switch(requestCode) {

                case ACTIVITY_ASSIGN_COLOR:
                        Log.w(this.getClass().getName(), "back");
                        if (data == null) return;
        
                }               
         }
}

class SurfView extends SurfaceView implements SurfaceHolder.Callback,
OnGestureListener  {
        
        private String TAG  = "SurfView";
    private boolean is_dirty = true;

    private boolean block_block = false;
    private boolean block_after_draw = true;    

    /** The thread that actually draws the animation */
    private SurfThread thread;
        private GestureDetector mGestureDetector;


        public float offset_x = 0; // review this later
        public float offset_y = 0;
        
        public float x_velocity = 0; // review this later
        public float y_velocity = 0;            

        private float last_pos_x = 0;
        private float last_pos_y = 0;

        private int keep_on_trucking = -1;
        
        // used for managing timing in physics
    private long start_time = System.currentTimeMillis();
    private long end_time = 0;
    private long sleep_time = 0;
    private long diff_time = 0;
    private long action_period = 20; // 50 = 20fps      

    /** coords of bg circle */
    private float bX;
    private float bY;

    /** coords of pointer (m == mouse). */
    private float mX;
    private float mY;

    /** Handle to the surface manager object we interact with */
    private boolean hasSurface;

        class SurfThread extends Thread {
                
        private int mCanvasWidth = -1;
        private int mCanvasHeight = -1;

        /** !!! Message handler used by thread to interact with TextView */
        // private Handler mHandler;

        /** Used to figure out elapsed time between frames */
        private long mLastTime;

         /** The state of the game. One of READY, RUNNING, PAUSE,
LOSE, or WIN */
        private int mMode;

        /** Scratch rect object. */
        private RectF mScratchRect;

                Paint mPaint = new Paint();
                
                int transparent_white;
                
            /** Indicate whether the surface has been created & is ready to 
draw */
        private boolean mRunning = false;
                public boolean is_drawing = false;
                
                private ConditionVariable mCondition = new ConditionVariable();
                
            private SurfaceHolder mHolder;
            private Context mContext;
        
                public SurfThread(SurfaceHolder holder, Context context){
                        
                    mHolder = holder;
                    mContext = context;

                        mRunning = false;
                        init();
                }
                
                public void init(){
                        mPaint.setColor(Color.RED);
                }
                
                public void pause(){
                        synchronized (this) {
                                Log.v("PeepThread", "pause?");
                                //requestExitAndWait();
                                
                                setRunning(false);
                                mCondition.open();
                                //holdup = false;
                                
                        }
                }

        public void setRunning(boolean b) {
            mRunning = b;
        }
                
                public boolean holdup = false;

        public void do_draw(){

                is_dirty = true;
                block_after_draw = true;
                mCondition.open();
        }

        /** this is key to most everything */
        @Override
        public void run() {
                
                SurfaceHolder surfaceHolder = mHolder;
                mCondition = new ConditionVariable(false);
                
                Log.v("Peep Thread", "restarted?");
                
                mRunning = true;

            while (mRunning) {
                
                Log.v("Peep Thread", "run?");
                
                while (holdup){
                        
                        mCondition.block(100);
                        System.out.println ("not running?");
                        
                        if (!mRunning){
                                is_dirty = false;
                                break;
                        }
                }
                
                is_drawing = true;

                updatePhysics();
                
                if (is_dirty){
                        
                        Canvas c = null;
        
                        c = surfaceHolder.lockCanvas(null); // moved this out
of "try" loop as per Stoyan suggestion
        
                        try {
                            synchronized (surfaceHolder) {
                                draw_me(c);
                            }
        
                        } finally {
                            // do this in a finally so that if an exception is 
thrown
                            // during the above, we don't leave the Surface in 
an
                            // inconsistent state
                            if (c != null) {
                                surfaceHolder.unlockCanvasAndPost(c);
                            }
                        }
                        is_dirty = false;
                    }
                
                start_time = System.currentTimeMillis();
                
                is_drawing = false;
                
                // !!! this needs to work off a stack
                if (block_after_draw) {
                        mCondition.close();
                        mCondition.block();
                }
            }

            System.out.println ("thread killed?");

        }

        public void requestExitAndWait(){
                
                mRunning = false;
                
                try {
                        join();
                } catch (InterruptedException ex){
            // nothing is supposed to happen here
                // (left intentionally blank)
                }
        }

        /* Callback invoked when the surface dimensions change. */
        public void setSurfaceSize(int width, int height) {
            // synchronized to make sure these all change atomically
                
                // !!! TODO: make sure center of screen stays.  Might make
sense to draw a mini-screen_bubble to confirm.
                
            synchronized (mHolder) {

                // this can be improved - ask ben to write something that
will determine the smallest circle that will fit around the largest
square
                System.out.println ("setSurfaceSize");
        
                mCanvasWidth = width;
                mCanvasHeight = height;
            }
        }


        public void unpause() {
                
            // Move the real time clock up to now
            synchronized (mHolder) {
            }

            thread.do_draw();
        }

        /**
         * Draw operations go in here
         */
        private void draw_me(Canvas canvas) {

                canvas.drawColor(Color.WHITE); // draw background color
                
                        canvas.save();
                        canvas.translate(offset_x, offset_y);
                        
                        canvas.drawCircle(mX, mY, 60, mPaint);

                        canvas.restore();
                        canvas.translate(offset_x * -1, offset_y * -1);
        }

        /**
         * Figures the lander state (x, y, fuel, ...) based on the passage of
         * realtime. Does not invalidate(). Called at the start of draw().
         * Detects the end-of-game and sets the UI to the next state.
         */
        private void updatePhysics() {
                                
                end_time = System.currentTimeMillis();
                diff_time = (end_time - start_time);
                sleep_time = action_period - diff_time;
                
                if (sleep_time < 1) sleep_time = 1;
                
                        try {
                                Thread.sleep(sleep_time);
                        }
                        catch(InterruptedException ex) {

                        }

                        is_dirty = true;

                }
        }

    private void init(){
        // register our interest in hearing about changes to our surface
        
                mGestureDetector = new GestureDetector(this);
                mGestureDetector.setIsLongpressEnabled(false);  // true
                
                setLongClickable(false);

        hasSurface = false;
     }

    public SurfView(Context context, AttributeSet attrs) {
        super(context, attrs);

        init(); // prep stuff for view

        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);

        thread = new SurfThread(holder, context);
    }

    /**
     * Fetches the animation thread corresponding to this View.
     *
     * @return the animation thread
     */
    public SurfThread getThread() {
        return thread;
    }

    /**
     * Standard window-focus override. Notice focus lost so we can pause on
     * focus lost. e.g. user switches to take a call.
     */
    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        
   }

    /* Callback invoked when the surface dimensions change. */
    public void surfaceChanged(SurfaceHolder holder, int format, int
width, int height) {
        thread.setSurfaceSize(width, height);
//        if (thread != null)   thread.setSurfaceSize(width, height);
    }

    /*
     * Callback invoked when the Surface has been created and is ready to be
     * used.
     */
    public void surfaceCreated(SurfaceHolder holder) {
        // start the thread here so that we don't busy-wait in run()
        // waiting for the surface to be created

        is_dirty = true;

        Log.w(this.getClass().getName(), thread.isAlive() + "?");

        
                try {
                    thread.start();
                } catch (Exception e){
                        // thread.run();
                        System.out.println ("resurfaced"); // DEAL WITH THIS 
DIFF
                }

    }

    /*
     * Callback invoked when the Surface has been destroyed and must no longer
     * be touched. WARNING: after this method returns, the Surface/Canvas must
     * never be touched again!
     */
    public void surfaceDestroyed(SurfaceHolder holder) {
        // we have to tell thread to shut down & wait for it to finish, or else
        // it might touch the Surface after we return and explode
        boolean retry = true;

        thread.setRunning(false);

        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                
            }
        }

        Log.v(this.getClass().getName(), "SURFACE DESTROYED");

    }

        @Override
        public boolean onTouchEvent(MotionEvent event) {
                return false;
        }


        @Override
        public boolean dispatchTouchEvent(MotionEvent event) {

                boolean returnValue = false;
                
                        is_dirty = true;
                        
                        returnValue  =  mGestureDetector.onTouchEvent(event);
                        returnValue  =  returnValue ?  returnValue : 
onTouchEvent(event);

                return returnValue;
        }
        
        public boolean onDown(MotionEvent event) {
                
                System.out.println ("down");
                thread.do_draw();
                return true;
        }

        public boolean onFling(MotionEvent first_event, MotionEvent
last_event, float velocityX, float velocityY) {
                return false;
        }

        public void onLongPress(MotionEvent event) {
                thread.do_draw();
        }
        
        public boolean onScroll(MotionEvent arg0, MotionEvent event, float
distance_x, float distance_y) {
                return false;
        }

        public void onShowPress(MotionEvent arg0) {
                // TODO Auto-generated method stub
        }

        public boolean onSingleTapUp(MotionEvent event) {
                
                mX = event.getX();
                mY = event.getY();
                thread.do_draw();

                return false;
        }
        
}

Thank You,
Jason








On Fri, Apr 24, 2009 at 12:03 PM, robotissues <[email protected]> wrote:
> I am stuck.  My main activity creates and starts a SurfaceView.  My
> app needs to access a listview via the options menu to change
> properties of the items shown in the view.
>
> Two strange things occur:
>
> 1.) When I scroll the listview quickly, the list sometimes gets
> farklempt.  Words overlap each other.
>
> 2.) When I select the item and the app returns to the main activity,
> the thread is no longer alive.
>
> If someone out there can offer help I will post the code.  This will
> take a little effort.  My code is loosely based upon LunarLander and
> the GLSurfaceView examples.  If there is a good example (more recent
> example) someone can point me to, that would be boss.
>
> Thank You

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to