Android常见问题

1、注册广播有哪几种方式,区别?

a、在代码中注册Broadcast Receiver,影响特定Activity的UI的Brocast Receiver通常在代码中注册。在代码中注册的接收器只会在包含他的应用程序组件运行时响应Broadcast Intent。在接受器用来更新一个Activity中的UI元素时,这样做很有帮助。在这种情况下,在onResume处理程序中注册接收器,并在onPause()中销毁它是一种很好的做法。


private IntentFilter filter = new IntentFilter(LifeformDetectedReceiver.NEW_LIFEFORM);
private LifeformDetectedReceiver receiver = new LifeformDetectedReceiver();

@override
public void onResume() {
	super.onResume();
	//注册Brocadcast Receiver
	registerReceiver(receiver, filter);
}
@override
public void onPause() {
	//注销Broadcast Receiver
	unregisterReceiver(receiver);
	super.onPause();
}

b、在应用程序的manifest中注册Broadcast Receiver,通过这种方式注册Broadcast Receiver总是活动的,并且即使当应用程序被终止或者未启动时,也可以接收Broadcast Intent。

要在应用程序的manifest中包含一个Broadcast Receiver,可以在application节点中添加一个receiver标签,以指定要注册的Broadcast Receiver的类名。接收器节点需要包含一个Intent-filter标签来指定要监听的动作字符串。

<receiver android:name=".LifeformDetectedReceiver">

<intent-filter>

<action android:name="com.paad.alien.action.NEW_LIFEFORM"/>

</intent-filter>

</receiver>

上面的“.LifeformDetectedReceiver"实际上是一个自定义的继承BroadcastReceiver的类,intent-filter标签内的”com.padd.alien.action.NEW_LIFEFORM"则对应代码中的LifeformDetectedReceiver.NEW_LIFEFORM(这其实是LifeformDetectedReceiver类里的一个String变量)

public class MyReceiver extends BroadcastReceiver 

{

@override

public void onReceive(Context context, Intent intent)

{

//避免进行耗时操作,该方法存在的时间有些说法是不超过5秒,有些则说不超过10秒

Toast.makeText(context,"接收到的Intent的Action为:" + intent.getAction() + "\n消息内容是:" 

+ intent.getStringExtra("msg"), Toast.LENGTH_LONG).show();

}

}


<receiver android:name=".MyReceiver">

<intent-filter>

<action android:name="org.crazyit.action.CRAZY_BROADCAST" />

</intent>

</receiver>


发送广播

Intent intent = new Intent();

intent.setAction("org.crazyit.action.CRAZY_BROADCAST");

intent.putExtra("msg","simple message");

sendBroadcast(intent);


注册方式其实与Activity和service没多大区别。


2、Service怎样与Activity实现通信

绑定Activtiy并与之通信,通过startService()和stopService()启动、关闭Service时,Service与访问者之间基本不存在太多的关联,因此Service和访问者之间也无法进行通信、数据交换。应该用bindService()和unbindService()方法启动、关闭Service,借助IBinder可实现通信和数据交换。

bindService(Intent service, ServeiceConnection conn, int flags)

service:该参数通过Intent指定要启动的Service。

conn:该参数是一个ServiceConnection对象,该对象用于监听访问者与Service之间的连接情况。当访问者与Service之间连接策划成功时将回调该ServiceConnection的onServiceConnected(ComponentName name, IBinder service)方法;如果失败,则回调onServiceDisconnected(ComponentName name)方法。

flags:指定绑定时是否自动创建Service(如果还未创建)。0,不自动创建,BIND_AUTO_CREATE,自动创建。

public class BindService extends Service

{

private MyBinder binder = new MyBinder();

......

//通过继承Binder实现IBinder类

public class MyBinder extends Binder

{

public int getCount()

{

//自定义方法具体实现

}

}

//必须实现的方法,绑定该Service时回调该方法

@override

public IBinder onBind(Intent intent)

{

//其它实现

return binder;

}

//@override

public void onCreate()

{

......

}

@override

public boolean onUnbind(Intent intent)

{

......

}

@override

public void onDestroy()

{

......

}

}


public class BindServericeTest extends Activity

{

BindServiece.MyBinder binder;

private ServiceConnection conn = new ServeiceConnection()

{

//当Activity与Service连接成功时回调该方法

@override

public void onServiceConnected(ComponentName name, IBinder service)

{

binder = (BindService.MyBinder) service;

}

@override

public void onServiceDisconnected(ComponentName name)

{

......

}

};

@override

public void onCreate(Bundle savedInstanceState)

{

......

//创建启动Service的Intent

final Intent itent = new Intent();

intent.setAction("org.crazyit.service.BIND_SERVICE");

......

//指定绑定Service

bindService(intent, conn, Service.BIND_AUTO_CREATE);

//解除绑定unbindService(conn);

}

}


3、Handler通信具体到源码是怎么实现的

Message:Handler接收和处理消息对象

Looper:每个线程只能拥有一个Looper。它的的Loop方法负责读取MessageQueue中的消息,读到消息之后就把消息交给发送该消息的Handler进行处理。

MessageQueue:消息队列,它采用先进先出的方式来管理Message。程序创建Looper对象时会在它的构造器中创建Looper对象。Looper提供的构造器源代码如下:

private Looper()

{

mQueue = new MessageQueue();

mRun = true;

mThread = Thread.currentThread();

}

程序在初始化Looper时会创建一个关联的MessageQueue,这个MessageQueue就负责管理消息。被Handler发送的消息必须被送到指定的MessageQueue。也就是说,如果希望Handler正常工作,必须在当前进程中有一个MessageQueue,否则消息就无法保存。所以,希望Handler正常工作,必须在当前进程有一个Looper对象,可分如下两种情况处理:

主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可通过Handler来发送、处理消息。

自己启动子进程,必须自己创建一个Looper对象并启动它。创建时调用它的prepare()方法即可。

public static final void prepare()

{

if(sThreadLocal.get() != null)

{

throw new RuntimeException("only one Looper may be created per thread");

}

sThreadLocal.set(new Looper());

}

然后调用Looper的静态loop()方法来启动它。loop()方法用一个死循环不断取出MessageQueue中的消息,交给对应的Handler进行处理。

new Thread(new Runnable() {

public Handler mHandler;

@override

public void run() {

Looper.prepare();

mHandler = new Handler();

{

@override

public void handleMessage(Message msg)

{

..........

}

};

Looper.loop();

}

}.start;


出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android只允许UI线程修改Activity里的UI组件。在实际Android应用开发中,尤其是动画的游戏开发中,需要让新启动的线程周期性地改变界面组件的属性值,这就需要Handler的消息传递机制来实现了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值