zoukankan      html  css  js  c++  java
  • 优雅的回调

    看看Android 原生的关于回调函数的用法:

    一,旋转角度变化的回调:

      1 /**
      2  * Helper class for receiving notifications from the SensorManager when
      3  * the orientation of the device has changed.
      4  */
      5 public abstract class OrientationEventListener {
      6     private static final String TAG = "OrientationEventListener";
      7     private static final boolean DEBUG = false;
      8     private static final boolean localLOGV = false;
      9     private int mOrientation = ORIENTATION_UNKNOWN;
     10     private SensorManager mSensorManager;
     11     private boolean mEnabled = false;
     12     private int mRate;
     13     private Sensor mSensor;
     14     private SensorEventListener mSensorEventListener;
     15     private OrientationListener mOldListener;
     16     
     17     /**
     18      * Returned from onOrientationChanged when the device orientation cannot be determined
     19      * (typically when the device is in a close to flat position).
     20      *
     21      *  @see #onOrientationChanged
     22      */
     23     public static final int ORIENTATION_UNKNOWN = -1;
     24 
     25     /**
     26      * Creates a new OrientationEventListener.
     27      * 
     28      * @param context for the OrientationEventListener.
     29      */
     30     public OrientationEventListener(Context context) {
     31         this(context, SensorManager.SENSOR_DELAY_NORMAL);
     32     }
     33     
     34     /**
     35      * Creates a new OrientationEventListener.
     36      * 
     37      * @param context for the OrientationEventListener.
     38      * @param rate at which sensor events are processed (see also
     39      * {@link android.hardware.SensorManager SensorManager}). Use the default
     40      * value of {@link android.hardware.SensorManager#SENSOR_DELAY_NORMAL 
     41      * SENSOR_DELAY_NORMAL} for simple screen orientation change detection.
     42      */
     43     public OrientationEventListener(Context context, int rate) {
     44         mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
     45         mRate = rate;
     46         mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
     47         if (mSensor != null) {
     48             // Create listener only if sensors do exist
     49             mSensorEventListener = new SensorEventListenerImpl();
     50         }
     51     }
     52     
     53     void registerListener(OrientationListener lis) {
     54         mOldListener = lis;
     55     }
     56 
     57     /**
     58      * Enables the OrientationEventListener so it will monitor the sensor and call
     59      * {@link #onOrientationChanged} when the device orientation changes.
     60      */
     61     public void enable() {
     62         if (mSensor == null) {
     63             Log.w(TAG, "Cannot detect sensors. Not enabled");
     64             return;
     65         }
     66         if (mEnabled == false) {
     67             if (localLOGV) Log.d(TAG, "OrientationEventListener enabled");
     68             mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
     69             mEnabled = true;
     70         }
     71     }
     72 
     73     /**
     74      * Disables the OrientationEventListener.
     75      */
     76     public void disable() {
     77         if (mSensor == null) {
     78             Log.w(TAG, "Cannot detect sensors. Invalid disable");
     79             return;
     80         }
     81         if (mEnabled == true) {
     82             if (localLOGV) Log.d(TAG, "OrientationEventListener disabled");
     83             mSensorManager.unregisterListener(mSensorEventListener);
     84             mEnabled = false;
     85         }
     86     }
     87 
     88     class SensorEventListenerImpl implements SensorEventListener {
     89         private static final int _DATA_X = 0;
     90         private static final int _DATA_Y = 1;
     91         private static final int _DATA_Z = 2;
     92         
     93         public void onSensorChanged(SensorEvent event) {
     94             float[] values = event.values;
     95             int orientation = ORIENTATION_UNKNOWN;
     96             float X = -values[_DATA_X];
     97             float Y = -values[_DATA_Y];
     98             float Z = -values[_DATA_Z];        
     99             float magnitude = X*X + Y*Y;
    100             // Don't trust the angle if the magnitude is small compared to the y value
    101             if (magnitude * 4 >= Z*Z) {
    102                 float OneEightyOverPi = 57.29577957855f;
    103                 float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;
    104                 orientation = 90 - (int)Math.round(angle);
    105                 // normalize to 0 - 359 range
    106                 while (orientation >= 360) {
    107                     orientation -= 360;
    108                 } 
    109                 while (orientation < 0) {
    110                     orientation += 360;
    111                 }
    112             }
    113             if (mOldListener != null) {
    114                 mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values);
    115             }
    116             if (orientation != mOrientation) {
    117                 mOrientation = orientation;
    118                 onOrientationChanged(orientation);
    119             }
    120         }
    121 
    122         public void onAccuracyChanged(Sensor sensor, int accuracy) {
    123 
    124         }
    125     }
    126     
    127     /*
    128      * Returns true if sensor is enabled and false otherwise
    129      */
    130     public boolean canDetectOrientation() {
    131         return mSensor != null;
    132     }
    133 
    134     /**
    135      * Called when the orientation of the device has changed.
    136      * orientation parameter is in degrees, ranging from 0 to 359.
    137      * orientation is 0 degrees when the device is oriented in its natural position,
    138      * 90 degrees when its left side is at the top, 180 degrees when it is upside down, 
    139      * and 270 degrees when its right side is to the top.
    140      * {@link #ORIENTATION_UNKNOWN} is returned when the device is close to flat
    141      * and the orientation cannot be determined.
    142      *
    143      * @param orientation The new orientation of the device.
    144      *
    145      *  @see #ORIENTATION_UNKNOWN
    146      */
    147     abstract public void onOrientationChanged(int orientation);
    148 }

    典型用法:

    public class DemoActivity extends Activity{
        
        private MyOrientationEventListener mOrientationListener;
        
        private class MyOrientationEventListener extends OrientationEventListener {
            public MyOrientationEventListener(Context context) {super(context);}
    
            @Override
            public void onOrientationChanged(int orientation) {
                android.util.Log.i(TAG, "onOrientationChanged: "+orientation);
            }
        }
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mOrientationListener = new MyOrientationEventListener(this);
        }
    
        @Override
        public void onResume() {
            mOrientationListener.enable();
        }
    
        @Override
        public void onPause() {
            mOrientationListener.disable();
        }
    }

    主要逻辑如下:

    1. 构造函数中new SensorEventListenerImpl类型对象mSensorEventListener

         */
        public OrientationEventListener(Context context, int rate) {
            mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
            mRate = rate;
            mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            if (mSensor != null) {
                // Create listener only if sensors do exist
                mSensorEventListener = new SensorEventListenerImpl();
            }
        }
        

    2. SensorEventListenerImpl的回调函数根据传感器的变化, 计算出一个角度, 传给抽象函数onOrientationChanged(orientation),该抽象函数就是继承类时必须要重写的

      public void onSensorChanged(SensorEvent event) {
                ......
                if (orientation != mOrientation) {
                    mOrientation = orientation;
                    onOrientationChanged(orientation);
                }
            }

     二,手势变化的回调:

    public class GestureDetector {
        /**
         * The listener that is used to notify when gestures occur.
         * If you want to listen for all the different gestures then implement
         * this interface. If you only want to listen for a subset it might
         * be easier to extend {@link SimpleOnGestureListener}.
         */
        public interface OnGestureListener {
       
            boolean onDown(MotionEvent e);
       
            void onShowPress(MotionEvent e);
          
            boolean onSingleTapUp(MotionEvent e);
           
            boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
    
            void onLongPress(MotionEvent e);
          
            boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
        }
    
        /**
         * The listener that is used to notify when a double-tap or a confirmed
         * single-tap occur.
         */
        public interface OnDoubleTapListener {
          
            boolean onSingleTapConfirmed(MotionEvent e);
            
            boolean onDoubleTap(MotionEvent e);
          
            boolean onDoubleTapEvent(MotionEvent e);
        }
    
        /**
         * The listener that is used to notify when a context click occurs. When listening for a
         * context click ensure that you call {@link #onGenericMotionEvent(MotionEvent)} in
         * {@link View#onGenericMotionEvent(MotionEvent)}.
         */
        public interface OnContextClickListener {
        
            boolean onContextClick(MotionEvent e);
        }
    
        /**
         * A convenience class to extend when you only want to listen for a subset
         * of all the gestures. This implements all methods in the
         * {@link OnGestureListener}, {@link OnDoubleTapListener}, and {@link OnContextClickListener}
         * but does nothing and return {@code false} for all applicable methods.
         */
        public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
                OnContextClickListener {
    
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }
    
            public void onLongPress(MotionEvent e) {
            }
    
            public boolean onScroll(MotionEvent e1, MotionEvent e2,
                    float distanceX, float distanceY) {
                return false;
            }
    
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                    float velocityY) {
                return false;
            }
    
            public void onShowPress(MotionEvent e) {
            }
    
            public boolean onDown(MotionEvent e) {
                return false;
            }
    
            public boolean onDoubleTap(MotionEvent e) {
                return false;
            }
    
            public boolean onDoubleTapEvent(MotionEvent e) {
                return false;
            }
    
            public boolean onSingleTapConfirmed(MotionEvent e) {
                return false;
            }
    
            public boolean onContextClick(MotionEvent e) {
                return false;
            }
        }

    典型用法:

       mGestureDetector = new GestureDetector(context, new GestureDetectorListener());
    
      @Override
        public boolean onTouchEvent(MotionEvent e) {
            mGestureDetector.onTouchEvent(e);
            return true;
        }
    
    
        public class GestureDetectorListener extends  GestureDetector.SimpleOnGestureListener {
            @Override
            public boolean onSingleTapConfirmed(MotionEvent e) {
                Log.i(TAG, "onSingleTapConfirmed: ");
                return true;
            }
        }

     值得学习的是SimpleOnGestureListener这种写法,public 静态内部类,保持了代码的模块化,同时方便了调用者,不用再去实现每一个接口方法,因为调用者关心的可能只是某一两个方法

    三,网络请求的回调

    本质上来讲, 这里其实没有必要用接口回调的,  线程里直接传入一个引用也可以达到同样的目的.

    接口主要用在类关系复杂时, 不方便持有对方引用的时候, 才考虑抽象出来一个接口, 但如果从通用性的角度来看, 这里用接口又比较好

  • 相关阅读:
    Design Pattern
    javascript summary
    nodejs template
    MVC---Case 1
    About js
    本地schemeApp扩展
    BNU4208:Bubble sort
    [置顶] think in java interview-高级开发人员面试宝典代码示例
    java+socket 简易聊天工具
    oracle 字段自增 两段代码搞定
  • 原文地址:https://www.cnblogs.com/hixin/p/8547726.html
Copyright © 2011-2022 走看看