1.监听
事件源:任何组件,buttun等.
事件监听器:myclicklistener
注册监听器:setxxxlistener
1)内部类作为事件监听器类:
可以访问外部类所有的界面组件.
2)外部类作为事件监听器类:
不能自由的访问界面的组件;
如果某个监听器确实需要被多个界面共享,而且主要是完成某种业务逻辑.
界面:
public class SendSms extends Activity
{
EditText address;
EditText content;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
address = (EditText)findViewById(R.id.address);
content = (EditText)findViewById(R.id.content);
Button bn = (Button)findViewById(R.id.send);
bn.setOnLongClickListener(new SendSmsListener(
this , address, content));
}
}
外部类:
public class SendSmsListener implements OnLongClickListener
{
private Activity act;
private EditText address;
private EditText content;
public SendSmsListener(Activity act, EditText address
, EditText content)
{
this.act = act;
this.address = address;
this.content = content;
}
@Override
public boolean onLongClick(View source)
{
String addressStr = address.getText().toString();
String contentStr = content.getText().toString();
SmsManager smsManager = SmsManager.getDefault();
PendingIntent sentIntent = PendingIntent.getBroadcast(act
, 0, new Intent(), 0);
smsManager.sendTextMessage(addressStr, null, contentStr
, sentIntent, null);
return false;
}
}
3)activity本身作为监听器,很混乱,不推荐
4)匿名内部类,大家都用的那种,不赘诉.
5)直接绑定到xml.android:οnclick="";
2.回调
Class A实现接口CallBack callback——背景1
class A中包含一个class B的引用b ——背景2
class B有一个参数为callback的方法f(CallBack callback) ——背景3
A的对象a调用B的方法 f(CallBack callback) ——A类调用B类的某个方法 C
然后b就可以在f(CallBack callback)方法中调用A的方法 ——B类调用A类的某个方法D
//这个是View的一个回调接口
/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
publicinterfaceOnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
voidonClick(View v);
}
packagecom.example.demoactivity;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
importandroid.widget.Toast;
/**
* 这个就相当于Class A
* @author xiaanming
* 实现了 OnClickListener接口---->背景一
*/
publicclassMainActivityextendsActivityimplementsOnClickListener{
/**
* Class A 包含Class B的引用----->背景二
*/
privateButton button;
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button1);
/**
* Class A 调用View的方法,而Button extends View----->A类调用B类的某个方法 C
*/
button.setOnClickListener(this);
}
/**
* 用户点击Button时调用的回调函数,你可以做你要做的事
* 这里我做的是用Toast提示OnClick
*/
@Override
publicvoidonClick(View v) {
Toast.makeText(getApplication(), "OnClick", Toast.LENGTH_LONG).show();
}
}
下面是View类的setOnClickListener方法,就相当于B类咯,只把关键代码贴出来
/**
* 这个View就相当于B类
* @author xiaanming
*
*/
publicclassViewimplementsDrawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
/**
* Listener used to dispatch click events.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
*/
protectedOnClickListener mOnClickListener;
/**
* setOnClickListener()的参数是OnClickListener接口------>背景三
* Register a callback to be invoked when this view is clicked. If this view is not
* clickable, it becomes clickable.
*
* @param l The callback that will run
*
* @see #setClickable(boolean)
*/
publicvoidsetOnClickListener(OnClickListener l) {
if(!isClickable()) {
setClickable(true);
}
mOnClickListener = l;
}
/**
* Call this view's OnClickListener, if it is defined.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
publicbooleanperformClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
if(mOnClickListener !=null) {
playSoundEffect(SoundEffectConstants.CLICK);
//这个不就是相当于B类调用A类的某个方法D,这个D就是所谓的回调方法咯
mOnClickListener.onClick(this);
returntrue;
}
returnfalse;
}
}
3.handle
出现的原因:android平台只允许主线程修改Activity的UI组件,这样就导致新启动的线程无法改变界面组件的属性值,如果要修改,就得用handle的消息传递机制.
Handle类的作用:
在新启动的线程中发送消息.
在主线程中获取,处理消息.
相当于在子线程里发个消息,主线程里接受到这个消息,然后修改组件,子线程只是发消息,修改还是在主线程
public class HandlerPostActivity1 extends Activity {
private Button btnMes1,btnMes2;
private TextView tvMessage;
// 声明一个Handler对象
private static Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.message_activity);
btnMes1=(Button)findViewById(R.id.btnMes1);
btnMes2=(Button)findViewById(R.id.btnMes2);
tvMessage=(TextView)findViewById(R.id.tvMessage);
btnMes1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 新启动一个子线程
new Thread(new Runnable() {
@Override
public void run() {
// tvMessage.setText("...");
// 以上操作会报错,无法再子线程中访问UI组件,UI组件的属性必须在UI线程中访问
// 使用post方式修改UI组件tvMessage的Text属性
handler.post(new Runnable() {
@Override
public void run() {
tvMessage.setText("使用Handler.post在工作线程中发送一段执行到消息队列中,在主线程中执行。");
}
});
}
}).start();
}
});
btnMes2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// 使用postDelayed方式修改UI组件tvMessage的Text属性值
// 并且延迟3S执行
handler.postDelayed(new Runnable() {
@Override
public void run() {
tvMessage.setText("使用Handler.postDelayed在工作线程中发送一段执行到消息队列中,在主线程中延迟3S执行。");
}
}, 3000);
}
}).start();
}
});
}
}
例子2:定时换图片
public class HandlerTest extends Activity
{
int[] imageIds = new int[]
{
R.drawable.java,
R.drawable.ee,
R.drawable.ajax,
R.drawable.xml,
R.drawable.classic
};
int currentImageId = 0;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView show = (ImageView) findViewById(R.id.show);
final Handler myHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
if (msg.what == 0x1233)
{
show.setImageResource(imageIds[currentImageId++
% imageIds.length]);
}
}
};
new Timer().schedule(new TimerTask()
{
@Override
public void run()
{
myHandler.sendEmptyMessage(0x1233);
}
}, 0, 1200);
}
}