Android 中Observer模式的使用
android实际上使用了大量的obverser 模式,最简单的就是onclicklistener,但是与一般的observer模式不同的是,view中定义了很多接口,如下所示:
/**
* Interface definition for a callback to be invoked when a touch event is
* dispatched to this view. The callback will be invoked before the touch
* event is given to the view.
*/
public interface OnTouchListener {
/**
* Called when a touch event is dispatched to a view. This allows listeners to
* get a chance to respond before the target view.
*
* @param v The view the touch event has been dispatched to.
* @param event The MotionEvent object containing full information about
* the event.
* @return True if the listener has consumed the event, false otherwise.
*/
boolean onTouch(View v, MotionEvent event);
}
/**
* Interface definition for a callback to be invoked when a view has been clicked and held.
*/
public interface OnLongClickListener {
/**
* Called when a view has been clicked and held.
*
* @param v The view that was clicked and held.
*
* return True if the callback consumed the long click, false otherwise
*/
boolean onLongClick(View v);
}
/**
* Interface definition for a callback to be invoked when the focus state of
* a view changed.
*/
public interface OnFocusChangeListener {
/**
* Called when the focus state of a view has changed.
*
* @param v The view whose state has changed.
* @param hasFocus The new focus state of v.
*/
void onFocusChange(View v, boolean hasFocus);
}
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
/**
* Interface definition for a callback to be invoked when the context menu
* for this view is being built.
*/
public interface OnCreateContextMenuListener {
/**
* Called when the context menu for this view is being built. It is not
* safe to hold onto the menu after this method returns.
*
* @param menu The context menu that is being built
* @param v The view for which the context menu is being built
* @param menuInfo Extra information about the item for which the
* context menu should be shown. This information will vary
* depending on the class of v.
*/
void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
}
每个接口执行不同的操作。
下面是一个相关的例子:
package com.fp.app.looper; import com.fp.app.debug.DebugLog; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; import android.widget.Button; public class Observer extends Activity implements OnClickListener ,OnFocusChangeListener{ public static final String TITLE = "title"; @Override public void setTitle(int titleId) { super.setTitle(titleId); } private Button btnMM; private Button btnMS; private Button btnSM; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.entry); findComponent(); setOnClickListener(); setOnFocusChangeListener(); } private void setOnClickListener() { btnMM.setOnClickListener(this); btnMS.setOnClickListener(this); btnSM.setOnClickListener(this); } private void setOnFocusChangeListener() { btnMM.setOnFocusChangeListener(this); btnMS.setOnFocusChangeListener(this); btnSM.setOnFocusChangeListener(this); } private void findComponent() { btnMM = (Button) this.findViewById(R.id.btn_mm); btnMS = (Button) this.findViewById(R.id.btn_ms); btnSM = (Button) this.findViewById(R.id.btn_sm); } @Override public void onClick(View v) { int id = v.getId(); switch (id) { case R.id.btn_mm: DebugLog.log("btnMM onclick"); break; case R.id.btn_ms: DebugLog.log("btnMS onclick"); break; case R.id.btn_sm: DebugLog.log("btnSM onclick"); break; default: break; } } @Override public void onFocusChange(View v, boolean hasFocus) { int id = v.getId(); switch (id) { case R.id.btn_mm: DebugLog.log("btnMM onFocusChange"); break; case R.id.btn_ms: DebugLog.log("btnMS onFocusChange"); break; case R.id.btn_sm: DebugLog.log("btnSM onFocusChange"); break; default: break; } } }
package com.fp.app.debug;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import android.util.Log;
public class DebugLog {
public final static boolean DEBUG = true;
public static void log(String message) {
if (DEBUG) {
String fullClassName = Thread.currentThread().getStackTrace()[3].getClassName();
String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
String methodName = Thread.currentThread().getStackTrace()[3].getMethodName();
int lineNumber = Thread.currentThread().getStackTrace()[3].getLineNumber();
Log.d(className + "." + methodName + "():" + lineNumber, message);
}
}
public static void printThreadId(String message) {
if (DEBUG) {
Log.d(message, String.valueOf(Thread.currentThread().getId()));
}
}
public static void log(String tag, String message) {
if (DEBUG) {
String methodName = Thread.currentThread().getStackTrace()[3].getMethodName();
int lineNumber = Thread.currentThread().getStackTrace()[3].getLineNumber();
Log.d(tag + "." + methodName + "():" + lineNumber, message);
}
}
public static void printTrace(String message) {
if (DEBUG) {
printIllegalArgumentException("", message);
}
}
public static String getStackTrace(Throwable throwable) {
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
throwable.printStackTrace(printWriter);
return writer.toString();
}
public static void printIllegalArgumentException(String tag, String arg) {
if (DEBUG) {
final Throwable throwable = new IllegalArgumentException(arg);
Log.w(tag, arg, throwable);
}
}
}
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.fp.app.looper" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".Observer" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:id="@+id/btn_mm"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="main thread to main thread" />
<Button android:id="@+id/btn_ms"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="main thread to sub thread" />
<Button android:id="@+id/btn_sm"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="sub thread to main thread" />
</LinearLayout>

浙公网安备 33010602011771号