优雅的回调
看看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 静态内部类,保持了代码的模块化,同时方便了调用者,不用再去实现每一个接口方法,因为调用者关心的可能只是某一两个方法
三,网络请求的回调
本质上来讲, 这里其实没有必要用接口回调的, 线程里直接传入一个引用也可以达到同样的目的.
接口主要用在类关系复杂时, 不方便持有对方引用的时候, 才考虑抽象出来一个接口, 但如果从通用性的角度来看, 这里用接口又比较好