android面试

1.请解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系。

简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理。
Message Queue(消息队列):用来存放通过Handler发布的消息,通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列。
Handler:可以发布或者处理一个消息或者操作一个Runnable,通过Handler发布消息,消息将只会发送到与它关联的消息队列,也只能处理该消息队列中的消息。
Looper:是Handler和消息队列之间通讯桥梁,程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的。
Handler:Handler接受到消息后调用handleMessage进行处理。
Message:消息的类型,在Handler类中的handleMessage方法中得到单个的消息进行处理。
在单线程模型下,为了线程通信问题,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对象。

2.如果有个100M大的文件,需要上传至服务器中,而服务器form表单最大只能上传2M,可以用什么方法。

使用Http协议上传数据,特别是在Android下,跟form没什么关系。传统的在web中,在form中写文件上传,其实浏览器所做的就是将我们的数据进行解析组拼成字符串,以流的方式发送到服务器,且上传文件用的都是POST方式,POST方式对大小没什么限制。

3、内存溢出和内存泄漏有什么区别?何时会产生内存泄漏?内存优化有哪些方法?

内存溢出通俗理解就是软件(应用)运行需要的内存,超出了它可用的最大内存。
内存泄漏就是我们对某一内存空间的使用,使用完成后没有释放。
内存优化:Android中容易内存溢出的部分,就是图片的加载,我们可以使用图片的压缩加上使用LruCache缓存的目的
来控制图片所能够使用的内存。还有对于比较耗资源的对象及时的关闭,例如Database Conn,各种传感器,Service等等。

4.AsyncTask使用在哪些场景?它的缺陷是什么?如何解决?

AsyncTask 运用的场景就是我们需要进行一些耗时的操作,耗时操作完成后更新主线程,或者在操作过程中对主线程的UI进行更新。
缺陷:AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还有一个缓冲队列,当线程池中已有128个线程,缓冲队列已满时,如果此时向线程提交任务,将会抛出RejectedExecutionException。
解决的方法:由一个控制线程来处理AsyncTask的调用判断线程池是否满了,如果满了则线程睡眠否则请求AsyncTask继续处理。

5.assest文件夹里放文件,对于文件的大小有没有限制?

assets目录更像一个附录类型的目录,Android不会为这个目录中的文件生成ID并保存在R类当中,因此它与Android中的一些类和方法兼容度更低。同时,由于你需要一个字符串路径来获取这个目录下的文件描述符,访问的速度会更慢。但是把一些文件放在这个目录下会使一些操作更加方便,比方说拷贝一个数据库文件到系统内存中。要注意的是,你无法在Android XML文件中引用到assets目录下的文件,只能通过AssetManager来访问这些文件。数据库文件和游戏数据等放在这个目录下是比较合适的。这两者中单个文件大小不能超过1M的错误描述也在传播,即如果读取超过1M的文件会报IOException,还引申出种种解决方案。不应该有这样的限制,为了验证这个说法写了个Demo,发现将近5M的压缩包在assets和raw中都能正常访问,在这里纠正一下,理论上只要打包不超过Android APK 50M大小的限制都是没有问题的。当然了,不排除是Android很早期的时候因为设备硬件原因aapt在编译的时候对这两个文件夹大小做出了限制,如果是这样,较新版的ADT应该不会出现这种情况。

6.启动一个程序,可以主界面点击图标进入,也可以从一个程序中跳转过去,二者有什么区别?

是因为启动程序(主界面也是一个app),发现了在这个程序中存在一个设置为<category android:name="android.intent.category.LAUNCHER" />的activity,所以这个launcher会把icon提出来,放在主界面上。当用户点击icon的时候,发出一个Intent:Intent intent = mActivity.getPackageManager().getLaunchIntentForPackage(packageName);
mActivity.startActivity(intent);跳过去可以跳到任意允许的页面,如一个程序可以下载,那么真正下载的页面可能不是首页(也有可能是首页),这时还是构造一个Intent,startActivity。
这个intent中的action可能有多种view,download都有可能。系统会根据第三方程序向系统注册的功能,为你的Intent选择可以打开的程序或者页面。所以唯一的一点不同的是从icon的点击启动的intent的action是相对单一的,从程序中跳转或者启动可能样式更多一些。本质是相同的。

7.程序之间的亲和性的理解。

1、默认情况下一个应用的所有Activity都是具有相同的affinity,都是从application中继承,application的affinity
默认就是manifest的包名。
2、affinity对Activity来说,就像是身份证一样,可以告诉所在的Task,自己属于其中的一员。
3、应用场合:
a:根据affinity重新为Activity选择合适的宿主Task;
b:与allowTaskReparenting属性配合;
c:启动Activity使用Intent设置了FLAG_ACTIVITY_NEW_TASK标记。


8.同一个程序,但不同的Activity是否可以放在不同的Task任务栈中?

可以放在不同的Task中。需要为不同的activity设置不同的affinity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。


9.横竖屏切换时候Activity的生命周期。

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。


10.AIDL的全称是什么?如何工作?

全称是:Android Interface Define Language(Android接口定义语言)
在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然, Java中不允许跨进程内存共享。
因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦。
AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL,需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class。
AIDL的创建方法:
AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型。
下面是些AIDL支持的数据类型:
1. 不需要import声明的简单Java编程语言类型(int,boolean等)
2. String, CharSequence不需要特殊声明

3. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型


11.dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念?

DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念。Dalvik是Google公司自己设计用于Android平台的Java虚拟机,每一个Dalvik 应用作为一个独立的Linux 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。

12. 什么是Activity?

四大组件之一,一般的,一个用户交互界面对应一个activity, activity 是Context的子类,同时实现了window.callback和keyevent.callback, 可以处理与窗体用户交互的事件. 我开发常用的的有ListActivity,PreferenceActivity 等…如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity.


13. 请描述一下Activity生命周期。

    onCreate:   在这里创建界面 ,做一些数据 的初始化工作
    onStart:    到这一步变成用户可见不可交互的
    onResume:   变成和用户可交互的,(在activity 栈系统通过栈的方式管理这些个Activity的最上面,运行完弹出栈,
则回到上一个Activity)
    onPause:    到这一步是可见但不可交互 的,系统会停止动画 等消耗CPU 的事情从上文的描述已经知道,应该在这里保存你的一些数据,因为这个时候你的程序的优先级降低,有可能被系统收回。在这里保存的数据,应该在onResume里读出来,注意:这个方法里做的事情时间要短,因为下一个activity不会等到这个方法完成才启动
    onstop:     变得不可见 ,被下一个activity覆盖了
    onDestroy:  这是activity被干掉前最后一个被调用方法了,可能是外面类调用finish方法或者是系统为了节省空间将它暂时性的干掉,可以用isFinishing()来判断它,如果你有一个Progress Dialog在线程中转动,请在onDestroy里把他cancel掉,不然等线程结束的时候,调用Dialog的cancel方法会抛 异常的。
onPause,onstop, onDestroy,三种状态下,activity都有可能被系统干掉为了保证程序的正确性,你要在onPause()里写上持久层操作的代码,将用户编辑的内容都保存到存储介质上(一般都是数据库 )。实际工作中因为生命周期的变化而带来的问题也很多,比如你的应用程序起了新的线程在跑,这时候中断了,你还要去维护那个线程,是暂停还是杀掉还是数据回滚,是吧?因为Activity可能被杀掉,所以线程中使用的变量和一些界面元素就千万要注意了,一般我都是采用Android的消息机制
[Handler,Message]来处理多线程和界面交互的问题。
其实这些方法都是两两对应的,onCreate创建与onDestroy销毁;onStart可见与onStop不可见;onResume可编辑(即焦点)与onPause;这6个方法是相对应的,那么就只剩下一个onRestart方法了,这个方法在Activity被onStop后,但是没有被onDestroy,在再次启动此Activity时就调用onRestart(而不再调用onCreate)方法;如果被onDestroy了,则是调用onCreate方法。


14. 两个Activity之间跳转时必然会执行的是哪几个方法。

一般情况比如说有两个activity,分别叫A,B ,当在A里面激活B组件的时候, A会调用onPause()方法,然后B调用onCreate(),onStart(),OnResume(),这个时候B覆盖了窗体,A会调用onStop()方法。如果B是透明的,或者是对话框的样式, 就不会调用onStop()方法。


15.横竖屏切换时候Activity的生命周期。

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次。
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次。
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法。


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

在AndroidManifest.xml文件当中设置当前activity的一个属性:android:theme="@android:style/Theme.Dialog"
 

17. 你后台的Activity被系统 回收怎么办?如果后台的Activity由于某原因被系统回收可了,如何在被系统回收之前保存当前状态?

除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.
protected void onSaveInstanceState(Bundle outState) {
       super.onSaveInstanceState(outState);
       outState.putLong("id", 1234567890);
}
public void onCreate(Bundle savedInstanceState) {
//判断 savedInstanceState是不是空.
//如果不为空就取出来
        super.onCreate(savedInstanceState);
}


18. 如何退出Activity?如何安全退出已调用多个Activity的Application?

1、抛异常强制退出:
该方法通过抛异常,使程序Force Close。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。
2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。
3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。
4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。
上面是网上的一些做法.
其实,可以通过intent的flag来实现。intent.setFlag(FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,然后在新的activity的oncreate方法里面 finish掉.
 

19. service是否在main thread中执行, service里面是否能执行耗时的操作?

默认情况,如果没有显示的指定service所运行的进程, Service和activity是运行在当前app所在进程的main thread(UI主线程)里面


20. 两个Activity之间怎么传递数据?
基本数据类型可以通过Intent传递数据 extras.putDouble(key, value) ;intent.putExtras(extras)
Application全局里面存放对象,自己去实现自己的application的这个类,基础系统的application , 每个activity都可以取到。
让对象实现implements Serializable 接口把对象存放到文件上。
让类实现Serializable 接口,然后可以通过 ObjectOutputStream ObjectInputStream
       //ObjectInputStream
       //ObjectOutputStream
           FileOutputStream fos = new FileOutputStream(new File("/sdcard/studnet.obj"));
           ObjectOutputStream oos = new ObjectOutputStream(fos);
           oos.writeObject(new Student());
 

21. 怎么让在启动一个Activity是就启动一个service?

在activity的onCreate()方法里面startService();


22. 同一个程序,但不同的Activity是否可以放在不同的Task任务栈中?

可以放在不同的Task中。需要为不同的activity设置不同的affinity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。


23. Activity怎么和service绑定,怎么在activity中启动自己对应的service?

bindService().  让activity能够访问到 service里面的方法构建一个intent对象,
Intent service = new Intent(this,MyService.class);
通过bindService的方法去启动一个服务,ServiceConnection 对象(重写onServiceConnected
和OnServiceDisconnected方法)和BIND_AUTO_CREATE.
       private class myconn implements ServiceConnection
       {
              public void onServiceConnected(ComponentName name, IBinder service) {
                     // TODO Auto-generated method stub
                     //可以通过IBinder的对象 去使用service里面的方法
              }
              public void onServiceDisconnected(ComponentName name) {
                     // TODO Auto-generated method stub
              }
       }


24. 什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?
在Service的生命周期中,被回调的方法比Activity少一些,只有onCreate, onStart, onDestroy,onBind和onUnbind。
通常有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。
1、通过startService
    Service会经历 onCreate 到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。
    如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。
2、通过bindService  
    Service会运行onCreate,然后是调用onBind, 这个时候调用者和Service绑定在一起。调用者退出了,Srevice就会调用onUnbind->onDestroyed方法。
    所谓绑定在一起就共存亡了。调用者也可以通过调用unbindService方法来停止服务,这时候Srevice就会调用
onUnbind->onDestroyed方法。
需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢?
一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又bindService,Service只被创建一次。
如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。
如果service运行期间调用了bindService,这时候再调用stopService的话,service是不会调用onDestroy方法的,service就stop不掉了,只能先UnbindService, 再StopService。

如果一个service通过startService 被start之后,多次调用startService 的话,service会多次调用onStart方法。多次调用stopService的话,service只会调用一次onDestroyed方法。

如果一个service通过bindService被start之后,多次调用bindService的话,service只会调用一次onBind方法。
多次调用unbindService的话会抛出异常。


25. 不用service,B页面为音乐播放,从A跳转到B,再返回,如何使音乐继续播放?

这个问题问的很山寨.默认不做任何处理,B里面的音乐都能播放。遇到问题, 可以随机应变,灵活发挥,多考虑些细节,比如说这个题就可以这样说,说说你对startActivityForResult的理解(),A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐。


26. 什么是IntentService?有何优点?

异步处理服务。优点是Acitivity的进程,当处理Intent的时候,会产生一个对应的Service。Android的进程处理器现在会尽可能的不kill掉你。非常容易使用。
 
27. 什么时候使用Service?
拥有service的进程具有较高的优先级。官方文档告诉我们,Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1.如果service正在调用onCreate,  onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。
2.如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.
3.如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4.如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。
       1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作.
       2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.
       3.远程的service如果被启动起来,可以被多次bind, 但不会重新create.  索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.
 
28. 请描述一下Intent 和 Intent Filter。
Intent在Android中被翻译为"意图",熟语来讲就是目的,他们是三种应用程序基本组件—activity,service和broadcast receiver之间互相激活的手段。 在调用Intent名称时使用ComponentName也就是类的全名时为显示调用。
这种方式一般用于应用程序的内部调用,因为你不一定会知道别人写的类的全名。我们来看看隐式Intent怎么用? 
首先我们先配置我们的Activity的Intent Filter  
<intent-filter>      
<action android:name="com.example.project.SHOW_CURRENT" /> 
</intent-filter>  
这样在调用的时候指定Intent的action,系统就是自动的去对比是哪个intent-filter符合我们的Activity,找到后就会启动Activity。  一个intent filter是IntentFilter类的实例, 但是它一般不出现在代码中,而是出现在android Manifest文件中, 以<intent-filter>的形式. (有一个例外是broadcast receiver的intent filter是使用Context.registerReceiver()来动态设定的, 其intent filter也是在代码中创建的.) 一个filter有action, data,category等字段. 一个隐式intent为了能被某个intent filter接受, 必须通过3个测试. 一个intent为了被某个组件接受, 则必须通过它所有的intent filter中的一个. 
 
29. Intent传递数据时,可以传递哪些类型数据?
基本类型可以传的,还有类是可以的,不过要继承Serializable这个接口。
Intent间传送数据一般有两种常用的办法:
1.extra
2.data. 
extra可以用Intent.putExtra放入数据。新启动的Activity可用Intent.getExtras取出来Bundle, 然后用Bundles.getLong, getInt, getBoolean, getString等函数来取放进入的值。
而data则是传输url。url可以是指我们熟悉的http, ftp 等网络地址,也可以指content来指向ContentProvider提供的资源。Intent.setData可以放入数据,Intent.getData可以取出数据。


30. 说说Activity,Intent,Service是什么关系。
一个Activity通常是一个单独的屏幕,每一个Activity都被实现为一个单独的类,这些类都是从Activity基类中继承来的,Activity类会显示由视图控件组成的用户接口,并对视图控件的事件做出响应。
Intent的调用是用来进行架构屏幕之间的切换的。Intent是描述应用想要做什么。Intent数据结构中两个最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。
Android Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序进程的上下文里。需要通过某一个Activity或者其他Context对象来调用。
Activity跳转到Activity,Activity启动Service,Service打开Activity都需要Intent表明跳转的意图,以及传递参数,Intent是这些组件间信号传递的承载者。

31. 请描述一下BroadcastReceiver。

BroadcastReceiver用于接收并处理广播通知(broadcast announcements)。多数的广播是系统发起的,如地域变换、电量不足、来电短信等。程序也可以播放一个广播。程序可以有任意数量的broadcast receivers来响应它觉得重要的通知。Broadcast receiver可以通过多种方式通知用户: 启动activity、使用NotificationManager、开启背景灯、振动设备、播放声音等,最典型的是在状态栏显示一个图标,这样用户就可以点它打开看通知内容。通常我们的某个应用或系统本身在某些事件(电池电量不足、来电短信)来临时会广播一个Intent出去,我们利用注册一个broadcastreceiver来监听这些Intent并获取Intent中的数据。


32. 在manifest和代码中如何注册和使用BroadcastReceiver

在android的manifest中注册
<receiver android:="" name="“Receiver1”">
                <intent-filter>
                            <!----和Intent中的action对应--->
                            <actionandroid: name="“com.forrest.action.mybroadcast”/">
                </actionandroid:></intent-filter>
</receiver>
1、 IntentFilter filter = new IntentFilter(“com.forrest.action.mybroadcast”);//和广播中Intent的action对应;
2、 MyBroadcastReceiver br= new MyBroadcastReceiver();
3、 registerReceiver(br, filter);

33.请介绍下ContentProvider是如何实现数据共享的。

一个程序可以通过实现一个Content provider的抽象接口将自己的数据完全暴露出去,而且Content provider是以类似数据库中的表的方式将自己的数据暴露。Content provider存储和检索数据,通过它可以让所有的应用程序访问到,这也是应用程序之间唯一共享数据的方法。
要想使应用程序的数据公开化,可通过2种方法:创建一个数据自己的Content Provider或者将你的数据添加到一个已经存在的Content Provider中,前提是有相同数据类型并且有写入Content Provider的权限,Android提供了Content Resolverr,外界的程序可以通过Content Resolver接口访问Content Provider提供的数据。

34.请介绍下Android的数据存储方式。

Android提供了5中存储数据的方式,分别是以下几种:
1、使用Shared Preferences存储数据,用来存储key-value,pairs格式的数据,它是一个轻量级的键值存储机制,只可以存储基本数据类型。
2、使用文件存储数据,通过FileInputStream和FileOutputStream对文件进行操作。在Android中,文件是一个应用程序私有的,一个应用程序无法读写其他应用程序的文件。
3、使用SQLite数据库存储数据,Android提供的一个标准数据库,支持SQL语句。
4、使用Content Provider存储数据,是所有应用程序之间数据存储和检索的一个桥梁,它的作用就是使得各个应用程序之间实现数据共享。它是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取数据,操作数据。系统也提供了音频、视频、图像和个人信息等几个常用的Content Provider。如果你想公开自己的私有数据,可以创建自己的Content Provider类,或者当你对这些数据拥有控制写入的权限时,将这些数据添加到Content Provider中实现共享。外部访问通过Content Resolver去访问并操作这些被暴露的数据。
5、使用网络存储数据

35.请介绍下Android中常用的五种布局。

最常用的布局方式为Absolute Layout、Relative Layout、Linear Layout、FrameLayout、TableLayout。其中Linear Layout和Relative Layout是最常用的方式,他们可以通过在xml配置文件或者代码中进行布局。
1、Frame Layout是最简单的布局方式,放置的控件都只能罗列到左上角,控件会有重叠,不能进行复杂的布局。
2、Linear Layout可以通过orientation属性设置线性排列的方向是垂直还是纵向的,每行或每列只有一个元素,可以进行复杂的布局。
3、Absolute Layout可以让子元素指定准确的x、y坐标值,并显示在屏幕上。Absolute Layout没有页边框,允许元素之间相互重叠。它是绝对坐标,所以在实际中不提倡使用。
4、Relative Layout允许子元素制定他们相对于其他元素或父元素的位置(通过ID制定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其他元素将以屏幕中央的相对位置来排列。这个是相对于Absolute Layout的,采用相对坐标,所以在实际中比较常用。
5、Table Layout将以子元素的位置分配到行或列。一个Table Layout由许多的Table Row组成,每个Table Row都会定义一个row。Table Layout容器不会显示row、column或者cell的边线框。每个row拥有0个或多个的cell; 和html中的table差不多。在实际中也经常使用。

36.谈谈UI中, Padding和Margin有什么区别?

Padding是控件的内容相对控件的边缘的边距,而Margin是控件边缘相对于其他控件的边距。

37.android本身的一些限制,比如apk包大小限制,读取大文件时的时间限。

apk包大小限制不好说,有的apk为100M,还是能装到手机上。一般的apk大小为5~10M左右。读取大文件的时间应该是在main线程里面,时间限制为5秒左右。

38.ListView如何提高其效率?

1、使用分页加载,不要一次性加载所有数据。
2、复用convertView。在getItemView中,判断converView是否为空,如果不为空,可复用。
3、异步加载图片。Item中如果包含有webimage,那么最好异步加载。
4、快速滑动时,不显示图片。当快速滑动列表(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLE和SCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来。


39.Android程序与Java程序的区别?

1、执行入口点,Android基于Mainfest.xml配置文件中的intent-filter,Java基于Main
2、UI,Android基于Activity,Java基于Frame
3、Android基于配置文件,Java不是。
4、Android基于组件Activity,Service,Broadcast Receiver,Content Provider,Java不是。

40.谈谈对Android NDK的理解。

android NDK是一套工具,允许Android应用开发者嵌入从C、C++源代码编译来的本地机器代码到各自的应用软件包中。
1、 NDK是一系列工具的集合。
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者帮助时巨大的。
NDK集成了交叉编辑器,并提供了相应的mk文件隔离CPU、平台、API等差异,开发人员只需要简单修改mk文件(指出“那些文件需要编译”、“编译特性要求”等),就可以创建出so。NDK可以自动将so和Java应用一起打包,极大的减轻了开发人员的打包工作。
2、NDK提供了一份稳定、功能有限的API头文件声明。这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、log库(liblog)。

41.谈谈Android的优点和不足之处。

优点:
1、android是开源、市场占有率大。
2、android能够有丰富的硬件选择。
3、android是一款基于Linux平台的开源操作系统,从而避免了专利壁垒,是一款完全免费的只能手机平台。
4、由于android是google开发的,因此能够无缝结合Google应用。
缺点:
1、安全与隐私。手机与互联网紧密联系,个人隐私很难得到保守。

42.Android系统中GC什么情况下会出现内存泄露呢?

导致内存泄露主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为“有效的活动”,同时不会被释放。要确定对象所占内存将被回收,我们就要确认该对象不会再被使用。典型的做法是把对象数据成员设为null或者从集合中移除该对象。当出现以下情况时,会造成内存泄露:
1、 数据库的cursor没有关闭。
2、 构造adapter时,没有使用缓存contentview。
3、 Bitmap对象不使用时,采用recycle()释放内存。
4、 Activity中的对象的生命周期大于activity。
调试方法: DDMS==>HEAPSIZE==>dataobject==>[TotalSize]

43.Android UI中的View如何刷新。

Android中对View的更新方式有很多种,使用时要区分不同的应用场合。要分清的是:多线程和双缓冲。
1、不使用多线程和双缓冲
这种情况最简单,一般只希望View在发生改变时对UI进行重绘。你只需要Activity中显式调用View对象中的invalidate()方法即可。系统会自动调用View的onDraw()方法。
2、使用多线程和不使用双缓冲
这种情况下需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报错:android.view.ViewRoot$ CalledFromWrongThreadException: only theoriginal thread that created a view hierarchy can touch its views。
这时候你需要创建一个继承了android.os.handler的子类,并重写handleMessage方法。Android.os.Handle是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量,你可以直接调用View对象中的invalidate()方法。也就是说:在新线程中创建并发送一个Message,然后在主线程中捕获、处理该消息。
3、使用多线程和双缓冲
Android的SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现Surfaceholder.Callback接口。由于SurfaceHolder.Callback接口,新线程就不要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制完新的图像后调用unlockCanvasand Post解锁。

44.对android虚拟机的理解,包括内存管理机制垃圾回收机制。

android虚拟机有dalvik,以及4.4以后出现的ART,这2种。
dalvik是执行的时候编译+运行,安装比较快,开启应用比较慢,应用占用空间小。ART是安装的时候就编译好了,执行的时候直接就可以运行的,安装慢,开启应用快,占用空间大。
用个比喻来说就是,骑自行车dalvik 是已经折叠起来的自行车,每次骑都要先组装自行车才能骑ART 是已经组装好的自行车,每次骑直接上车就能走人效率高在开启的时候,运行中的速度是差不多的。
Android的内存管理,Android的程序由Java语言编写,所以Android的内存管理与Java的内存管理相似。程序员通过new为对象分配内存,所有对象在java堆内分配空间;然而对象的释放是由垃圾回收器来完成的。C/C++中的内存机制是“谁污染,谁治理”,java的就比较人性化了,给我们请了一个专门的清洁工(GC 垃圾回收 GabageCollection)。
垃圾回收机制,使得Java程序员在编写程序的时候不再需要考虑内存管理。垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收。

45.Framework工作方式及原理,Activity是如何生成一个view的,机制是什么。

所有的框架都是基于反射和配置文件(manifest)的。
普通情况:Activity创建一个view是通过ondraw画出来的,画这个view之前呢,还会调用onmeasure方法来计算显示的大小。
特殊情况:Surfaceview是直接操作硬件的,因为视频播放对帧数有要求,onDraw效率太低,不够使,Surfaceview直接把数据写到显存。

46.什么是ANR 如何避免它?

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

47.如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?

可以将dictionary.db文件复制到Eclipse Android工程中的resaw目录中。所有在resaw目录中的文件不会被压缩,这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到resaw目录中

48.如何将打开res aw目录中的数据库文件?

在Android中不能直接打开res aw目录中的数据库文件,而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中,然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得resaw目录中资源的InputStream对象,然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。

49.Android引入广播机制的用意?

a:从MVC的角度考虑(应用程序内)
其实回答这个问题的时候还可以这样问,android为什么要有那4大组件,现在的移动开发模型基本上也是照搬的web那一套MVC架构,只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构,它们之间有时候是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便几大组件的信息和数据交互。
b:程序间互通消息(例如在自己的应用程序内监听系统来电)
c:效率上(参考UDP的广播协议在局域网的方便性)
d:设计模式上(反转控制的一种应用,类似监听者模式)

50.如果后台的Activity由于某种原因被系统回收,如何在回收之前保存当前状态。

这个知识点使用描述的方式来回答的,同样问题,我们在基本概念小整理(一)的17题问过了,那边是用代码回答的。
onSaveInstanceState().
程序中的某一个ActivityA 在运行时,主动或被动的运行另一个新的Activity B,这个时候A会执行onSaveInstanceState()。B完成以后又回来找A,这个时候有两种情况:一是A被回收,二是A没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState;而没被回收的就直接执行onResume(),跳过onCreate()。

51.Android 事件分发机制原理。

1、 Android事件分发是先传递到ViewGroup,再由ViewGroup传递到View的。
2、 在ViewGroup中可以通过onInterceptTouchEvent方法对事件传递进行拦截,onInterceptTouchEvent方法返回true代表不允许事件继续向子View传递,返回false代表不对事件进行拦截,默认返回false。
3、子View中如果将传递的事件消费掉,ViewGroup中将无法接收到任何事件。


52.Android 绘图机制原理。

View树的绘制是一个递归的过程,从ViewGroup一直向下遍历,直到所有的子view都完成绘制,View树的源头是ViewRoot。
ViewRoot中包含了窗口的总容器DecorView,ViewRoot中的performTraversal()方法会依次调用decorView的measure、layout、draw方法,从而完成view树的绘制。
invalidate()方法会导致View树的重新绘制,而且view中的状态标志mPrivateFlags中有一个关于当前视图是否需要重绘的标志位DRAWN,也就是说只有标志位DRAWN置位的视图才需要进行重绘。当视图调用invalidate()方法时,首先会将当前视图的DRAWN标志置位,之后有一个循环调用parent.invalidateChildinParent(),这样会导致从当前视图依次向上遍历直到根视图ViewRoot,这个过程会将需要重绘的视图标记DRAWN置位,之后ViewRoot调用performTraversals()方法,完成视图的绘制过程。

53.Android WindowManager。

WindowManager主要用来管理窗口的一些状态、属性、view增加、删除、更新、窗口顺序、消息收集和处理等。通过Context.getSystemService(Context.WINDOW_SERVICE)的方式可以获得WindowManager的实例.WindowManager继承自ViewManager,里面涉及到窗口管理的三个重要方法,分别是:addView()、 updateViewLayout()、removeView()。
在WindowManager中还有一个重要的静态类LayoutParams.通过它可以设置和获得当前窗口的一些属性。
我们先来看看addView()方法,在addView中,会利用LayoutParams获得window的View属性,并为每个window创建ViewRoot,ViewRoot是View和WindowManager之间的桥梁,真正把View传递给WindowManager的是通过ViewRoot的setView()方法,ViewRoot实现了View和WindowManager之间的消息传递。在将主窗口添加到WindowManger时,它首先会建立一个代理对象:
wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)并且打开会话(IWindowSession),之后Window将通过该会话与WindowManager建立联系。br />ViewRoot通过IWindowSession把窗口添加到WindowManager中。ViewRoot继承了Handler,实际上它的本质就是一个Handler,窗口中View的事件处理、消息发送、回调等将通过ViewRoot来处理。
这样就完成了把窗口添加到WindowManager中,并交由WindowManager来管理窗口的view、事件、消息收集处理等。

54.Android 进程间通信方式。

进程:在 Android 里面,进程是一组组件的集合。默认下,同一个应用的所有组件都运行在同一个进程中并且大多数程序不必改变这一状况.然而,如果你非要与众不同,也可以通过修改 AndroidManifest.xml 文件中修改四大组件(activity,service,receiver和provider)的process 属性来指定该组件运行在哪一个进程里。
由于 Android 本身设计的原因,进程间的数据是无法直接共享的,如果我们需要知道不同进程间的一些数据,就需要进行进程间通信操作。下面总结了以下进程间通信的一些方法。
1、Intent数据共享
Activity:
Intent intent = new Intent();
intent.setClassName("otherpackage","OtherActivity");
intent.putExtra("key","value");
startActivity(intent);
OtherActivity:
String value = getIntent().getStringExtra("key");
2、Broadcast广播跨进程通信
Intent broadcast = new Intent("my.broadcast.action");
broadcast.putExtra("key","value");
sendBroadcast(broadcast);
3、Content Provider
比如获取一个联系人的详情。联系人的详情时存在系统里面的,我们的应用一定不会和系统程序在一个进程,Content Provider 很明显就是一个跨进程通信的方法。
4、AIDL
AIDL(Android Interface Definition Language)Android接口定义语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。
5、Messnger
们可以在客户端发送一个Message给服务端,在服务端的handler中会接收到客户端的消息,然后进行对应的处理,处理完成后,再将结果等数据封装成Message,发送给客户端,客户端的handler中会接收到处理的结果。
6、文件
通过读写同一个文件的确是可以做到进程间通信的。

55.你是怎么设计项目架构的?

经典架构有MVC,MVP,MVVM,CLEAN等。
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写。
MVP全名是Model View Presenter,是模型(model)-视图(view)-表示器(presenter)的缩写。
所有架构,都是为了解耦,提高维护性。
解耦可在生产中实际效果是,把一个大工程,拆分成多个小工程,每个工程之间功能相互独立,可单独测试。把单线程变成多线程,一个人一年的工作量,拆成12个人,一个月就能做完。每个人只专注于自己那部分,对于大项目,或者工期紧的项目是非常重要的。要掌握好度,简单的功能无需再分。


56.BaseActivity、BaseFragment怎么设计?

如果是只有一个Activity的App就没有必要写BaseActivity,大于一个一般可以写BaseActivity。
每个Activity通常都是绑定视图,绑定控件,监听控件,获取Bundle,跳转Activity还有一些很有些烦人的小功能如:Toast,findViewById,我们都可以封装一层简化他们的使用。
不仅是Activity要搞一个基类,Fragment也要搞一个基类,这样可以大大减少重复代码,而且管理起来还比较容易,保持了样式的一致,也要预留个性化相应的方法。

57.你项目中的package划分,是按照层次划分的呢,还是按照功能划分的呢?

如果涉及团队协作开发,建议按模块划分。因为业务模块之间的耦合性相对于层级的耦合性要低,这样程序员在开发模块时,基本上要开发action、service、orm,这样开发的接触面比较全,而且基本上不需要与其它模块进行交互,减少沟通交流时间,能提高开发效率。如果按照层级划分,那么多人开发时,会存在action依赖service,而service由别人开发,会涉及到交流、沟通(如:action需要的业务方法,需要先告诉service开发人员……等等若干情况)

58.Android OOP AOP。

OOP,即Object Oriented Programming,面向对象编程。
AOP,即Aspect Oriented Programming,面向切向编程。
OOP,问题或者功能都被划分到一个一个的模块里边。每个模块专心干自己的事情,模块之间通过设计好的接口交互。OOP的精髓是把功能或问题模块化,每个模块处理自己的家务事。但在现实世界中,并不是所有问题都能完美得划分到模块中。有些功能是横跨并嵌入众多模块里的,比如打印日志,比如统计某个模块中某些函数的执行时间等。这些功能在各个模块里分散得很厉害,可能到处都能见到。
AOP的目标是把这些功能集中起来,放到一个统一的地方来控制和管理。如果说,OOP如果是把问题划分到单个模块的话,那么AOP就是把涉及到众多模块的某一类问题进行统一管理。比如我们可以设计两个Aspects,一个是管理某个软件中所有模块的日志输出的功能,另外一个是管理该软件中一些特殊函数调用的权限检查。


59.Android 图片异步加载。

1、采用多线程。将耗时的操作放在子线程中待其拿到数据后发一条消息到主线程中,从而在主线程中进行更新显示。
2、AsyncTask。异步线程加载图片。进行耗时操作比如加载图片要求不要阻塞UI线程,就必须使用异步任务。AsyncTask是不需要借助thread+handler即可实现异步任务的组件,使用起来比较简单且更轻量级一些。
3、LruCache。缓存已经加载过的图片。

60.Android 缓存策略。

缓存管理方法是数据库和文件,通常保存到sdcard。数据库如(SQLite)缓存方式。文件如.txt。
必须要说的是,LruCache、DiskLruCache。LruCache只是管理了内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从网络上重新加载一次图片,这显然非常耗时。对此,Google又提供了一套硬盘缓存的解决方案:DiskLruCache(非Google官方编写,但获得官方认证)。
介绍一下三级缓存,内存缓存(从内存中获取图片显示)、本地缓存(内存中没有从sd卡获取)、网络缓存(从网络下载并保存入本地和内存)

附上郭神相关博文链接: http://blog.csdn.net/guolin_blog/article/details/28863651

61.Android 线程池。

线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。
不需要处理的时候可以将它shutdow掉,同时当我们定义了一个线程池之后,可以复用线程而不需要开启更多线程,这点对于我们手机开发是至关重要的,你开启的thread越多意味着你的app内存消耗越多,速度也就越来越慢,提高现有线程的复用很有必要。
线程池的好处:
1、复用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
2、能有效控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。
3、能对线程进行简单的管理。并提供定时执行以及指定间隔循环执行等功能。
线程池包括:newCachedThreadPool()缓存型线程池、newFixedThreadPool()固定型线程池、newScheduledThreadPool()调度型线程池、SingleThreadExecutor 单例线程

62.Android 消息队列模型。

Android通过Looper、Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环)。
Android系统中,Looper负责管理线程的消息队列和消息循环。我们可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。
一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper)。
Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。
Handler的作用是把消息加入特定的(Looper)消息队列中,并分发和处理该消息队列中的消息。构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建。

63.Android 排序算法

1、直接选择排序。将数据分成两个区域,有序区与无序区。排序的时候是每次从无序区中选择出最小的数,然后插入到有序区中的最末尾,从而形成更大的有序区。直到无序区中的数为零,结束排序。
2、冒泡排序。相邻的两个数两两进行比较,拿从小到大说明,进行冒泡排序后会将大的数沉到底部,将小得数浮到顶部。所以冒泡说法由此得名。
3、直接插入排序。将需要排序的关键数与前面已经排好序的数据从后往前进行比较,使其插入到合适的位置。
4、归并排序。采用的是分治的思想,将待排序的序列分成若干组,保证每组都有序,然后再进行合并排序,最终使整个序列有序。
5、快速排序。将一个待排序序列分成两个部分,以其中的一个数据作为分界线,其中一部分小于这个分界线的数据,另一部分大于这个分界线的数据。因为采用递归的思想,再对这两个序列进行快速排序,直到所以的数据都是有序的。
6、希尔排序。记录增量来进行分组,再对分组内部进行直接插入排序,随着增量的不断减小,直到增量减小到1时,即每个分组中的数据量为1,此时排序结束。
7、堆排序。采用树的形式的数据结构来进行排序的,其中每一个堆都是完全二叉树。堆排序分为大根堆与小根堆,大根堆(小根堆)表示在完全二叉树中,所用的非叶子节点都大于等于(小于等于)他们左右子节点(存在)。所以堆的顶点不是最大数就是最小数。这样的话我们就可以借助这种性质,每次都取出大根堆(小根堆)的顶点数,形成有序序列。
来源:七大排序算法总结(java): https://segmentfault.com/a/1190000005753446

64.Android 设计模式。

1、单例模式。确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2、工厂方法模式。定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
3、抽象工厂模式。为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。
4、模版方法模式。定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
5、建造者模式。将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
6、代理模式。为其他对象提供一种代理以控制对这个对象的访问。
7、原型模式。用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。
8、中介者模式。用一个中介者对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使耦合松散,而且可以独立地改变它们之间的交互。中介者模式的优点适当地使用中介者模式可以避免同事类之间的过度耦合,使得各同事类之间可以相对独立地使用。使用中介者模式可以将对象间一对多的关联转变为一对一的关联,使对象间的关系易于理解和维护。使用中介者模式可以将对象的行为和协作进行抽象,能够比较灵活的处理对象间的相互作用。
9、命令模式。意图:将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求排队或记录日志,以及支持可撤销的操作。动机:将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来。
10、责任链模式。使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
11、装饰模式。又名包装(Wrapper)模式,装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
12、策略模式。定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。策略模式的好处在于你可以动态的改变对象的行为。
13、适配器模式。基于现有类所提供的服务,向客户提供接口,以满足客户的期望。适配器模式的用意是要改变源的接口,以便于目标接口相容。缺省适配的用意稍有不同,它是为了方便建立一个不平庸的适配器类而提供的一种平庸实现。
14、迭代器模式。提供一种方法访问一个容器对象中各个元素,而又不暴露该对象的内部细节。
15、组合模式。将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。对象通过实现(继承)统一的接口(抽象类),调用者对单一对象和组合对象的操作具有一致性。
16、观察者模式。定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
17、门面模式。外部与一个子系统的通信必须通过一个统一的门面对象进行。
18、备忘录模式。在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存的状态。 19、访问者模式。封装某些作用于某种数据结构中各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。访问者模式是对象的行为模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变。
20、状态模式。当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。
21、解释器模式。给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。
22、享元模式。复用我们内存中已存在的对象,降低系统创建对象实例的性能消耗。Flyweight在拳击比赛中指最轻量级,即“蝇量级”或“雨量级”,这里选择使用“享元模式”的意译,是因为这样更能反映模式的用意。享元模式是对象的结构模式。享元模式以共享的方式高效地支持大量的细粒度对象。23、桥梁模式。将抽象和实现解耦,使得两者可以独立地变化。桥梁模式的用意是“将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化”。
来源:Android 设计模式: http://blog.csdn.net/banketree/article/details/24985607

65.Android 虚拟机。

1、Dalvik虚拟机。安卓4.4以前。JIT编译器 即时编译器。Dalvik经过优化后,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个Dalvik应用作为一个独立的Linux进程执行,独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭。其实就是每一个应用都是作为独自的虚拟机运行,与其他应用互不牵扯。
2、ART虚拟机。安卓4.4以后。AOT这种预编译。在应用程序安装的过程中,ART就已经将所有的字节码重新编译成了机器码。应用程序运行过程中无需进行实时的编译工作,只需要进行直接调用。减少了手机的电量消耗,提高了移动设备的续航能力,在垃圾回收等机制上也有了较大的提升。

66.Android 性能优化。

性能优化目的是为了减少大多数用户感知到的卡顿。
1、布局复杂。布局深度,复杂度和控件数量。
2、内存抖动。多图会造成频繁的GC,在Android中的GC操作必须暂停所有其余操作,过多的GC会产生内存抖动,对系统性能造成非常大的影响。
3、过度绘制。在一帧内同一点被重复绘制多次,这造成了系统不必要的损耗,极大浪费了系统资源。
来源 知乎 :https://www.zhihu.com/question/30033704
4、把费时的操作(比如网络请求、数据库操作或者复杂的计算)从主线程移动到一个单独的线程中。
5、避免ANR。不要在主线程(UI线程)里面做繁重的操作。
6、在线程中初始化查询操作。当查询操作正在后台处理时,展示数据也不是即时的,但是你可以使用CursorLoader对象来加快速度,这个操作可以使Activity和用户之间的互动不受影响。使用这个对象后,你的App会为ContentProvider初始化一个独立的后台线程进行查询,当查询结束后就会给调用查询的Activity返回结果。
7、如果初始化操作很费时,请展示一个欢迎界面。
8、电量消耗。优化网络请求与数据解析。
9、流量占用。没有网络连接,请让你的应用跳过网络操作。使用流量时,提示用户是否进行大资源下载。
来源:十大技巧优化Android App性能 :http://mobile.51cto.com/abased-455556.htm



1、基础很重要。这个相信大家都深有体会。
2、项目要深入。做项目不能浅尝辄止,这个参加过面试的人应该都会有所体会。
3、心态很重要。跟高考一样,面试中心态不好,会很影响临场的发挥。
4、细节决定成败。从基础到项目,这个都会有所体现。
5、坚持写博客。虽然面试到现在,只有一个面试官看了我的博客,但写博客真的是一件有百利而无一害的事情。
6、凡事要讲究缘分。有些时候,有些事,确实要看缘分,所以把心放宽些,不要刻意放大一些痛苦。
7、付出总会有所收获,问题的关键在于你是否坚持的足够久。认识的一些付出了很多努力的小伙伴,虽然也是一路磕磕绊绊,但最终都有了比较好的结果。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
面试是评估一个人技能和能力的重要环节。在Android面试,除了基础知识的掌握外,还需要注意交流和语言组织能力。基础知识的牢固掌握是面试的基础,但有些人可能在实际表达存在困难。因此,在准备面试时,可以使用思维导图等工具来梳理知识点,帮助自己更好地组织语言。从简到繁、从外到内的方式可以帮助我们更好地展开回答。生成思维导图后,可以按照这个体系一条条地进行讲解,并在每个点上进行延伸,这样可以延长自己的说话时间,提高通过面试的概率。\[1\]\[2\] 在Android,进程之间是不能互相访问的,因此需要使用多进程通信技术。Android特有的多进程通信技术是Binder。通常情况下,一个应用是一个进程,但是Android一个应用也可以有多个进程,可以通过指定android:process属性来给四大组件指定进程。其以“:”开头的为私有进程,不以“:”开头的为共有进程。\[3\] 在Android面试,除了基础知识和多进程通信,还有其他重要的话题,如Android架构、UI设计、性能优化等。准备面试时,建议全面了解这些话题,并能够清晰地表达自己的观点和经验。 #### 引用[.reference_title] - *1* *2* *3* [android面试实用篇](https://blog.csdn.net/wang_yong_hui_1234/article/details/105579401)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值