一些公司的面试题

Activity的启动模式
    standard  每次都会新建,每个Task都可以有,且每个Task都可以有多个实例(每个Task都可以有,且可以有多个)
    singleTop 当前实例如果在栈顶,就不新建实例,调用其OnNewIntent。 如不在栈顶,则新建实例     (每个Task都可以有,且可以有多个,在栈顶时可复用)
    singleTask 新建一个Task,如果已经有其他的Task并且包含该实例,那就直接调用那个Task的实例。(只有一个Task中会有)
    singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)

通过Intent传递一些二进制数据的方法有哪些?
    1). 使用Serializable接口实现序列化,这是Java常用的方法。
    2). 实现Parcelable接口,这里Android的部分类比如Bitmap类就已经实现了,同时Parcelable在Android AIDL中交换数据也很常见的。

Android应用的入口点?
    其实在android.app.Application这个包的onCreate才是真正的Android入口点,只不过大多数开发者无需重写该类,他的继承关系如下图:
java.lang.Object
   ↳ android.content.Context
     ↳ android.content.ContextWrapper
       ↳ android.app.Application
android.app.Application类包含了4个公开的方法
void  onConfigurationChanged(Configuration newConfig)
void  onCreate()  //这里才是真正的入口点。
void  onLowMemory()
void  onTerminate()


Android的一些XML解析器
    XmlPull、SAX、DOM


SAX、DOM、PULL解析xml的原理,以及各自优缺点
    1. DOM是W3C指定的一套规范标准,核心是按树形结构处理数据,DOM解析器读入XML文件并在内存中建立一个结构一模一样的“树,树各节点和XML各标记对应,通过操纵此“树”来处理XML中的文件, DOM可以读取XML也可以向XML文件中插入数据。相对来说,编程容易,开发人员只需要调用建树的指令,然后利用APIs访问所需的树节点来完成任务。
    使用DOM我们可以指定要访问的元素进行随机访问,随意修改文件树,从而修改XML文件。尤其是向前处理时非常容易。(双向)
     DOM是基于内存的,不管文件有多大,都会将所有的内容预先装载到内存中。从而消耗很大的内存空间。但可移植。
    2.SAX是基于事件驱动(所谓事件驱动,是指一种基于回调(callback)机制的程序运行方法)的。SAX以类似于流的形式读取XML文件,分析能够立即开始,而不是等待所有的数据被处理,也就是说读入文档的过程和解析的过程是同时进行的。SAX解析器采用了基于事件的模型,它在解析XML文档的时候可以触发一系列的事件,当发现指定的TAG的时候,可以激活一个回调方法,告诉该方法指定的标签已经找到。当某个事件被触发时,才获取相应的XML的部分数据,需要编程者手动处理所有的事件。甚至不必解析整个文档,它可以在某个条件得到满足时停止解析。从而不管XML文件有多大,都只占用了少量的内存空间。效率比较高。
     SAX只能对XML进行读取,而不能在文件中插入数据。这也是SAX的一个缺点。
    SAX的另一个缺点:因为事件触发是有时序性的,所以SAX分析器提供的是一种对XML文档的顺序访问机制,对于已经分析过的部分,不能再重新倒回去处理。此外,单向导航很难同时访问同一文档的不同部分数据。同DOM分析器相比,SAX分析器对XML文档的处理缺乏灵活性。
    3.PULL解析XML在Android中用到的比较多,而且PULL技术已经被集成到Android系统中,所以在使用PULL的时候不需要额外引入到jar。Android中要是使用上述的四种方式,需要引入额外的jar,当然JavaEE中使用PULL技术进行解析的话,就需要引入PULL所需的jar了。
    其实PULL技术和SAX技术差不多,Pull解析器和SAX解析器虽有区别但也有相似性。他们的区别为:
SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束,而Pull解析器的工作方式为允许你的应用程序代码从解析器中主动获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。Android系统中和Pull方式相关的包为org.xmlpull.v1,在这个包中提供了Pull解析器的工厂类XmlPullParserFactory和Pull解析器XmlPullParser,前者实例调用newPullParser方法创建后者实例,接着后者实例就可以调用getEventType()和next()等方法依次主动提取事件,并根据提取的事件类型进行相应的逻辑处理。
而他们的相似性在运行方式上,Pull解析器也提供了类似SAX的事件,开始文档START_DOCUMENT和结束文档END_DOCUMENT,开始元素START_TAG和结束元素END_TAG,遇到元素内容TEXT等,但需要调用next()方法提取它们(主动提取事件)。


SAX
sax是一个用于处理xml事件驱动的“推”模型;
优点:解析速度快,占用内存少,它需要哪些数据再加载和解析哪些内容。
缺点:它不会记录标签的关系,而是需要应用程序自己处理,这样就会增加程序的负担。
DOM
dom是一种文档对象模型;
优点:dom可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构,dom技术使得用户页面可以动态的变化,如动态显示隐藏一个元素,改变它的属性,增加一个元素等,dom可以使页面的交互性大大增强。
缺点:dom解析xml文件时会将xml文件的所有内容以文档树方式存放在内存中。
PULL
pull和sax很相似,区别在于:pull读取xml文件后触发相应的事件调用方法返回的是数字,且pull可以在程序中控制,想解析到哪里就可以停止解析。 (SAX解析器的工作方式是自动将事件推入事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。pull是一个while循环,随时可以跳出,而sax不是,sax是只要解析了,就必须解析完成。)


Activity的生命周期。
    创建 oncreate -  启动onstart – 恢复 onResume – 暂停 onPause – 结束 onEnd – 销毁onDestroy
如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态?
    在”暂停 onPause” 状态将数据保存。


如何将一个Activity设置成窗口的样式。
    设置Theme。


Android的数据存储方式。
    sharedPreference,文件,数据库SQlite,网络存储 。

请介绍下ContentProvider是如何实现数据共享的。
    一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content providers是以类似数据库中表的方式将数据暴露。Content providers存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。
如何通过一套标准及统一的接口获取其他应用程序暴露的数据?
Android提供了ContentResolver,外界的程序可以通过ContentResolver接口访问ContentProvider提供的数据。
    定义自己的ContentProvider类,该类需要继承Android系统提供的ContentProvider基类。
在Manifest.xml 文件中注册ContentProvider,(四大组件的使用都需要在Manifest文件中注册) 注册时需要绑定一个URL。
例如: android:authorities="com.myit.providers.MyProvider"
说明:authorities就相当于为该ContentProvider指定URL。 注册后,其他应用程序就可以通过该Uri来访问MyProvider所暴露的数据了。
其他程序使用ContentResolver来操作。
调用Activity的ContentResolver获取ContentResolver对象
调用ContentResolver的insert(),delete(),update(),query()进行增删改查。
  


AIDL的全称是什么?如何工作?能处理哪些类型的数据?解释AIDL.
    AIDL全称Android Interface Definition Language(AndRoid接口描述语言)是一种接口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程跨界对象访问的目的.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.理论上, 参数可以传递基本数据类型和String, 还有就是Bundle的派生类, 不过在Eclipse中,目前的ADT不支持Bundle做为参数。
    
下面是些AIDL支持的数据类型:
1. 不需要import声明的简单Java编程语言类型(int,boolean等)
2. String, CharSequence不需要特殊声明
3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型。


    具体实现步骤如下:
1、创建AIDL文件, 在这个文件里面定义接口, 该接口定义了可供客户端访问的方法和属性。
2、编译AIDL文件, 用Ant的话, 可能需要手动, 使用Eclipse plugin的话,可以根据adil文件自动生产java文件并编译, 不需要人为介入。
3、在Java文件中, 实现AIDL中定义的接口. 编译器会根据AIDL接口, 产生一个JAVA接口。这个接口有一个名为Stub的内部抽象类,它继承扩展了接口并实现了远程调用需要的几个方法。接下来就需要自己去实现自定义的几个接口了.
4、向客户端提供接口ITaskBinder, 如果写的是service,扩展该Service并重载onBind ()方法来返回一个实现上述接口的类的实例。
5、在服务器端回调客户端的函数. 前提是当客户端获取的IBinder接口的时候,要去注册回调函数, 只有这样, 服务器端才知道该调用那些函数。
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型。


DIP、DPI分别是什么?
Dpi(像素密度)
是指屏幕上每英寸(1英寸 = 2.54 厘米)距离中有多少个像素点。如果屏幕为 320*240,屏幕长 2 英寸宽 1.5 英寸,Dpi = 320 / 2 = 240 / 1.5 = 160。

DIP
也可以叫做dp,长度单位,同一个单位在不同的设备上有不同的显示效果,具体效果根据设备的密度有关。


注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。
    Android广播机制(两种注册方法)
在android下,要想接受广播信息,那么这个广播接收器就得我们自己来实现了,我们可以继承BroadcastReceiver,就可以有一个广播接受器了。有个接受器还不够,我们还得重写BroadcastReceiver里面的onReceiver方法,当来广播的时候我们要干什么,这就要我们自己来实现。
    动态注册:
    1.//生成广播处理  
smsBroadCastReceiver = new SmsBroadCastReceiver();
    2. 实例化过滤器并设置要过滤的广播   
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
    3.注册广播
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter);
    静态注册(是在AndroidManifest.xml中配置广播 )
 <!--广播注册-->
        <receiver android:name=".SmsBroadCastReceiver">
            <intent-filter android:priority="20">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>  
两种注册类型的区别是:
     1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。
     2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。


在单线程模型中Message、Handler、Message Queue、Looper之间的关系。
    在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列), 线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换。下面将对它们进行分别介绍:
1. Message
     Message消息,理解为线程间交流的信息,处理数据后台线程需要更新UI,则发送Message内含一些数据给UI线程。
2. Handler
     Handler处理者,是Message的主要处理者,负责Message的发送,Message内容的执行处理。后台线程就是通过传进来的 Handler对象引用来sendMessage(Message)。而使用Handler,需要implement 该类的 handleMessage(Message)方法,它是处理这些Message的操作内容,例如Update UI。通常需要子类化Handler来实现handleMessage方法。
3. Message Queue
     Message Queue消息队列,用来存放通过Handler发布的消息,按照先进先出执行。
     每个message queue都会有一个对应的Handler。Handler会向message queue通过两种方法发送消息:sendMessage或post。这两种消息都会插在message queue队尾并按先进先出执行。但通过这两种方法发送的消息执行的方式略有不同:通过sendMessage发送的是一个message对象,会被 Handler的handleMessage()函数处理;而通过post方法发送的是一个runnable对象,则会自己执行。
4. Looper
     Looper是每条线程里的Message Queue的管家。Android没有Global的Message Queue,而Android会自动替主线程(UI线程)建立Message Queue,但在子线程里并没有建立Message Queue。所以调用Looper.getMainLooper()得到的主线程的Looper不为NULL,但调用Looper.myLooper() 得到当前线程的Looper就有可能为NULL。
     对于子线程使用Looper,API Doc提供了正确的使用方法:
     这个Message机制的大概流程:
     1. 在Looper.loop()方法运行开始后,循环地按照接收顺序取出Message Queue里面的非NULL的Message。
     2. 一开始Message Queue里面的Message都是NULL的。当Handler.sendMessage(Message)到Message Queue,该函数里面设置了那个Message对象的target属性是当前的Handler对象。随后Looper取出了那个Message,则调用 该Message的target指向的Hander的dispatchMessage函数对Message进行处理。
     在dispatchMessage方法里,如何处理Message则由用户指定,三个判断,优先级从高到低:
     1) Message里面的Callback,一个实现了Runnable接口的对象,其中run函数做处理工作;
     2) Handler里面的mCallback指向的一个实现了Callback接口的对象,由其handleMessage进行处理;
     3) 处理消息Handler对象对应的类继承并实现了其中handleMessage函数,通过这个实现的handleMessage函数处理消息。
     由此可见,我们实现的handleMessage方法是优先级最低的!
     3. Handler处理完该Message (update UI) 后,Looper则设置该Message为NULL,以便回收!
     在网上有很多文章讲述主线程和其他子线程如何交互,传送信息,最终谁来执行处理信息之类的,个人理解是最简单的方法——判断Handler对象里面的 Looper对象是属于哪条线程的,则由该线程来执行!
     1. 当Handler对象的构造函数的参数为空,则为当前所在线程的Looper;
     2. Looper.getMainLooper()得到的是主线程的Looper对象,Looper.myLooper()得到的是当前线程的Looper对象。
    

什么是ANR 如何避免它?
    ANR:Application Not Responding,五秒
在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了:
对输入事件(如按键、触摸屏事件)的响应超过5秒
意向接受器(intentReceiver)超过10秒钟仍未执行完毕
Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intent broadcast)。
因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 -- 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题。

 

什么情况会导致Force Close ?如何避免?能否捕获导致其的异常?
    一般像空指针啊,可以看起logcat,然后对应到程序中 来解决错误。


Android本身的api并未声明会抛出异常,则其在运行时有无可能抛出runtime异常,你遇到过吗?诺有的话会导致什么问题?如何解决?
    会有运行时异常, 运行时异常无需捕捉

 

android:paddingLeft与android:layout_marginLeft的区别
    当按钮分别设置以上两个属性时,得到的效果是不一样的。
android:paddingLeft="30px"
按钮上设置的内容(例如图片)离按钮左边边界30个像素
android:layout_marginLeft="30px"
整个按钮离左边设置的内容30个像素


Android 动画有哪几种?描述一下
    两种。 Tween动画和Frame动画。 Tween动画主要是透明度、尺寸伸缩、旋转、位移等效果。
Frame动画可以理解成gif, 一帧一帧的显示图片。比较常用的有滚动条效果。


返回键与Home键区别?
    back键默认行为是finish处于前台的Activity的即Activity的状态为Destroy状态为止,再次启动该Activity是从onCreate开始的(不会调用onSaveInstanceState方法)。Home键默认是stop前台的Activity即状态为onStop为止而不是Destroy,若再次启动它,会调用onSaveInstanceState方法,保持上次Activity的状态则是从OnRestart开始的---->onStart()--->onResume()


java线程的sleep(),wait(),notify(),yield()方法的区别?
    1.sleep()使线程休眠一段时间,一段时间结束后,线程进入可执行状态,但并不是立即执行,只是在被排程器调用的时候才执行。在休眠期间,并不释放所持有的“锁”;
    2.wait()使线程休眠一段时间,若设置参数,时间到时,线程就自动进入可执行状态。若没有,则需要notify()方法去调用。注意:wait()方法和notify()方法都时针对this对象的,调用wait()方法后,会释放加在对象上的“锁”。
    3.yield()使线程放弃执行的权利,进入可执行状态,也就意味着线程在yield()方法后,有可能又执行。使用yield()方法,线程并不释放自己锁持有的“锁”。
已有

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值