Android面试题集锦

来源:互联网 发布:软件poc产品 编辑:程序博客网 时间:2024/05/18 15:27

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()保证每个线程最多只有一个Looperpublic 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
原创粉丝点击