Android面试题集锦

blog中的问题是来自:http://www.nowcoder.com/discuss/3244
1.Android注册广播有几种方式
1)静态注册,在manifest文件中进行注册,这种方式注册的广播属于系统级广播。你的应用没打开也能收到广播。比如你要做一个收到某广播就启动你的应用的功能可以使用该方法。

 <receiver android:name="com.lc.ip.CallReceiver">
    <intent-filter >
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
    </intent-filter>
</receiver>

2)动态注册,在代码里执行一个rigisterBroadcastReciver的方法。这种你要自己作好反注册。这种广播可以做成你的应用启动后才监听,关闭后就不监听的效果。一般手机锁屏和解锁,电量改变这种频繁使用的都是动态注册,静态注册不起作用。以下代码是在服务中注册广播

public class RegisterService extends Service {

    private ScreenReceiver receiver;
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        //注册广播接收者
        //1.创建广播接收者对象
        receiver = new ScreenReceiver();
        //2.创建intent-filter对象
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        //注册广播接收者
        registerReceiver(receiver, filter);
    }
    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        //解除注册
        unregisterReceiver(receiver);
    }
}

2.绘制activity的生命流程图
(转http://www.cnblogs.com/AceIsSunshineRain/p/5183789.html
这里写图片描述

1.启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。

2.当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。

3.当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。

4.当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。

5.用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。

6.当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。

7.用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。

3.注册service需要注意什么
1.需要在androidmanifest中添加节点,name与包名类名完全一致。

<service android:name="com.example.lzz.RecorderService"></service>

2.自定义service时,androidmanifest中需要配置action,该action作为访问服务的唯一标识

        <service android:name="com.example.lzz.PayService">
            <intent-filter >
                <action android:name="com.lzz.sy"/>
            </intent-filter>
        </service>

3.在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自动解除,并且Service会自动停止);
4.使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
4.Service与Activity怎么实现通信
1.Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法,如果要主动通知Activity,我们可以利用回调方法。
2.Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好。在activity中动态注册广播,然后创建内部类继承BroadcastReceiver。
5.Android中的动画有哪些,区别是什么?
帧动画:帧动画就是Frame动画,即指定每一帧的内容和停留时间,然后播放动画。

//将帧动画的资源文件指定为IV的背景
        iv.setBackgroundResource(R.drawable.frameanimation);
        AnimationDrawable ad = (AnimationDrawable) iv.getBackground();
        ad.start();      

补间动画:就是通过两点间实现控件的特效,控件位置大小可能改变,但是其真正的属性没有随着改变,也就是说即便控件位移了,但是响应点击事件还是在原位置。主要包括四种效果:Alpha、Scale、Translate和Rotate。

public void translate(View v){
       ta = new TranslateAnimation(10, 100, 10, 100);
       //设置播放时间
       ta.setDuration(2000);
       //设置重复播放次数
       ta.setRepeatCount(1);
       //设置重复播放的模式
       ta.setRepeatMode(Animation.REVERSE);
       iv.startAnimation(ta);
   }

属性动画:与补间动画类似,但是它的属性会随着动画的变化而变化,这点和补间动画相反。属性动画只需要一个类就可以实现基本的特效,根据传入的不同特效参数而改变。
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, “这里是特效”, 10,100);

 public void translate(View v){
        //target:动画作用于哪个组件,第二个参数则是控制什么特效。
        ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10,100);
        oa.setDuration(2000);
        oa.setRepeatCount(1);
        oa.setRepeatMode(ValueAnimator.REVERSE);
        oa.start();
        }

6.Handle通信具体到源码,是怎么实现的
通过Looper,MessageQueue,Handler三大类实现。
1.Looper:每个线程只有一个looper,负责管理MessagQueue,会不断从MessageQueue中取出消息,并将消息分给对应的Handler处理。
2.MessageQueue:由Looper负责管理,它采用先进先出的方式管理Message.
3.Handler:它能把消息发送给Looper管理的MessageQueue,并负责处理Looper分给它的消息。
线程中使用Handler的步骤如下:
1.调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue.
对应函数源码:

//构造函数:
private Looper(){
    mQueue = new MessageQueue();
    mRun = true;
    mThread = Thread.currentThread();
}
//prepare()保证每个线程最多只有一个Looper
public static final void prepare(){
    if(sThreadLocal.get() != null){
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper());
}

2.有了Looper之后,创建Handler子类的实例,重写handleMessage()方法,该方法负责处理来自其他线程的消息。
3.调用Looper的loop()方法启动Looper,loop()方法是一个无线死循环,不断的寻找MessageQueue中的消息,只要有消息,便通知handler。
7.Handle的机制
1.Handler创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图所示。
2.Handler发送消息
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
3.Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值