您的位置:首页 > 职场人生

Android面试总结

2015-12-17 22:20 477 查看
面试准备:

1.多线程下载原理;

1.因为要多线程下载,要随机去指定位置,用一个randomAccessFile的流

1.请求服务器, 在本地创建一个大小跟服务器一样的文件

RandomAccessFile raf = new RandomAccessFile()

raf.setLength(length);

2.计算每个线程下载的位置.

blockSize = length / threadCount;

int startIndex = (i - 1) * blockSize;

int endIndex = i * blockSize - 1;

3.开启线程分别下载服务器上对应部分的资源(使用range字段),把下载下来的资源放在对应

的本地的文章上

conn.setRequestProperty("Range", "bytes=" + startIndex + "-

+ endIndex);

raf.seek(startIndex);

2.说说你对面向对象的理解:结合项目说

3.设计模式 单例 模板 装饰 观察者 工厂

被观察者继承observable,复写haschange()方法,notifyObserver()

观察者实现observer,回调update()方法;

4.handler机制

handler使用步骤:

* 1.looper.preapere(); 只能执行一次

/**

* 1.获取looper; mLooper = Looper.myLooper();

* 2.获取loooper的messagequeue mQueue =

mLooper.mQueue;

*/

* 2.创建handler.使用handler

new handler();

/**

* 拿到消息队列的引用 发消息发到消息队列里

并给消息排序

* enqueueMessage(queue, msg, uptimeMillis);

* 消息队列中boolean enqueueMessage(Message

msg, long when) {

*/

handler.sendEmptyMessage(0);

* 3.loop.loop();

/**

* 1.msg.target.dispatchMessage(msg);

* 2.handlemessage

*/

5.监听机制;

答:1.定义一个借口 2.声明一个setOnXXlistener方法;3.响应接口里的方法;4.调用

setOnXXlistener的方法

6.wait sleep区别;

wait所属是对象,sleep是Thread

wait释放锁,释放cpu资源

sleep不释放锁,不释放cpu资源

7.线程与进程的区别;

进程:正在运行中的程序,

线程:一个进程至少有一个线程(主线程),线程是程序的一条执行路径;

如:请求网络比较耗时,放在子线程,避免主线程堵塞;anr异常

11.接口与抽象类的区别;

下面比较一下两者的语法区别:

1.抽象类可以有构造方法,接口中不能有构造方法。

2.抽象类中可以有普通成员变量,接口中没有普通成员变量

3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象

的普通方法。

4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然

eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认

即为public abstract类型。

5. 抽象类中可以包含静态方法,接口中不能包含静态方法

6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任

意,但接口中定义的变量只能是public static final类型,并且默认即为public static

final类型。

7. 一个类可以实现多个接口,但只能继承一个抽象类。

应用:模板设计 父类方法中间的某段代码不确定,留给子类干,就用模板方法设计模式

自己理解:

抽象类主要用于对类中共性的抽取,比如模板设计方法

接口主要是自定义接口

14.activity fragemtn service 生命周期;

activity:oncreate onstart ouresume onpause onstop ondestory

?HOME键的执行顺序:onPause->onSaveInstanceState->onStop->onRestart->onStart-

>onResume

?BACK键的顺序: onPause->onStop->onDestroy->onCreate->onStart->onResume

A--->B :A的生命周期:onpause->onSaveInstanceState->onstop->onrestart->onStart-

>onResume

四种启动模式:standard

singTop:如果启动的activity在当前任务栈栈顶中,就不创建新的activity方法,而是调用原

来实例的onNewIntend();

如:添加浏览器书签

singleTask:只有一个实例,如果要激活的activity在任务栈中,就复用,调用onnewIntent方

法,

因为有些activity创建一次开销比较大,不如浏览器内核打开一个浏览器;browseractiity;

singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个

实例,不允许有别的Activity存在单独开一个任务栈;而且整个手机里只用一个activity实

例存在

如:呼叫界面:

service:

(1)startservice:

oncreate onstartcommand ondestory

(2)bindService:

oncreate onbind onUnbind ondestory

(3)混合生命周期

oncrate onstartcommand onbind onunbind ondestory

fragment:

onattatch oncreate oncreateview onactivitycreate onstart onresume

onpause onstop ondestoryView ondestory ondatach

13:内部类:

外部类可以访问内部类,但需要建立内部类对象

内部类在成员变量位置上,在外部其他类访问内部类非静态方法,且修饰符为默认

Outer.Inner inner = new Outer().new Inner();

inner.function();

如果为static

new Outer.Inner().functin();

如果访问内部类静态成员

Outer.Inner().function();

匿名内部类是因为方法总要调用,所以把内部类的定义,和调用简写了

12.数据库语句

13.集合和流的理解

8.自定义控件

/*

* view 对象显示的屏幕上,有几个重要步骤:

* 1、构造方法 创建 对象。

* 2、测量view的大小。 onMeasure(int,int);(空间渲染的过程必须测量)

* 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。

onLayout();

* 4、绘制 view 的内容 。 onDraw(Canvas)

*/

9.事件分发

viewgroup事件分发与消费:

首先自上而下分发,如果不消费,就往上传,看dispatcheventtouch方法的返回值结果,

如果是false,继续往上返回,

view的事件消费 :

imageView事件处理为例:

if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&

mOnTouchListener.onTouch(this, event)) {

return true;

}

return onTouchEvent(event);

setOntouchvent中ontouch返回为true,所有事件都消费,

如果为false,只响应action_down;

//点击事件的调用方式,就是回调方法

performClick();

public boolean performClick() {

....

if (mOnClickListener != null) {

...

//回调onclick方法

mOnClickListener.onClick(this);

...

}

...

}

点击事件和touch事件冲突解决:

ontouch返回true,onclick不会响应;

ontouch返回发了,onclick才会响应;

9.listview的优化

1.条目复用;避免内容溢出

2.保存孩子节点的id

避免多次遍历寻找孩子,提高效率,利用viewhodler

3.复杂条目的写法

复写两个方法

getViewTypeCount();

getItemViewType();

10.三级缓存

1.先从内存中取,没有再从文件中去,没有,从网络中取,

利用线程池,获取一个线程请求网络,并写入内存和文件中

再次进入时,就可以从内存中去,没有再从文件中取,

public ImageCacheUtil(Context context,Handler handler) {

int maxSize = (int) (Runtime.getRuntime().maxMemory()/8);

lruCache = new LruCache<String,Bitmap>(maxSize){

@Override

protected int sizeOf(String key, Bitmap value) {

//getRowBytes()一行上面对应像素点占用的大小

*value.getHeight()行号

return value.getRowBytes()*value.getHeight();

}

};

cacheDir = context.getCacheDir();

//2*cup核数+1

newFixedThreadPool = Executors.newFixedThreadPool(5);

this.handler = handler;

}

public Bitmap getBitmap(String imgUrl,int position){

//position为确认给那个imageview控件使用的tag

Bitmap bitmap = null;

//1,内存中去取

bitmap = lruCache.get(imgUrl);

if(bitmap!=null){

Log.i(tag, "从内存中获取到的图片");

return bitmap;

}

//2,文件中去取

bitmap = getBitmapFromLocal(imgUrl);

if(bitmap!=null){

Log.i(tag, "从文件中获取到的图片");

return bitmap;

}

//3,网络去下载

getBitmapFromNet(imgUrl,position);

Log.i(tag, "网络获取到的图片.......");

return null;

}

class RunnableTask implements Runnable{

private String imageUrl;

private int position;

public RunnableTask(String imageUrl,int position) {

this.imageUrl = imageUrl;

this.position = position;

}

@Override

public void run() {

//访问网络,下载图片

try {

URL url = new URL(imageUrl);

HttpURLConnection connection =

(HttpURLConnection) url.openConnection();

//读取超时时间()

connection.setReadTimeout(5000);

//链接超时时间()

connection.setConnectTimeout(5000);

connection.setRequestMethod("GET");

InputStream inputStream =

connection.getInputStream();

Bitmap bitmap = BitmapFactory.decodeStream

(inputStream);

//消息机制()

Message msg = new Message();

msg.what = SUCCESS;

msg.obj = bitmap;

msg.arg1 = position;

handler.sendMessage(msg);

//内存缓存

lruCache.put(imageUrl, bitmap);

//写入文件

writeToLocal(imageUrl, bitmap);

return ;

} catch (Exception e) {

e.printStackTrace();

}

Message msg = new Message();

msg.what = FAIL;

handler.sendMessage(msg);

}

}

private void writeToLocal(String imageUrl, Bitmap bitmap) {

String fileName;

try {

fileName = MD5Encoder.encode(imageUrl).substring(10);

File file = new File(cacheDir,fileName);

FileOutputStream fileOutputStream = new

FileOutputStream(file.getAbsolutePath());

//1,定义一个大小如果超过当前大小的时候,就需要进行等比例

压缩

bitmap.compress(CompressFormat.JPEG, 100,

fileOutputStream);

} catch (Exception e) {

e.printStackTrace();

}

}

private void getBitmapFromNet(String url,int position) {

newFixedThreadPool.execute(new RunnableTask(url,position));

}

private Bitmap getBitmapFromLocal(String imgUrl) {

String fileName;

try {

fileName = MD5Encoder.encode(imgUrl).substring(10);

File file = new File(cacheDir,fileName);

Bitmap bitmap = BitmapFactory.decodeFile

(file.getAbsolutePath());

//加入到内存中去(内存的效率要高)

lruCache.put(imgUrl, bitmap);

return bitmap;

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

}

图片错乱问题:

1.复用产生的问题:

解决:holder.imageview.settag(position);

if(bitmap!=null&&(Integer)holder.image.getTag()==position){

holder.image.setImageBitmap(bitmap);

}

11.介绍Android中的动画

1.view animation(平移,旋转等),drawable animation(帧动画),property animation(插值

器的使用,加入一些算法)

12.反射的原理:就是把Java类中的各种成分映射成相应的java类,(对类的解剖);

要想对一个类进行内容的获取,必须要先获得该字节码文件的对象

该对象类型是Class类型

Class class{

Filed filed;//字段

Method method;//构造函数

Contructor constructor;//构造函数

按照面向对象将字段,方法,构造器都封装成了对象;

}

13.java中内存的分析:(面试时画个图解释更好)

1.寄存器,cpu涉及的区域

2.本地方法区,是和系统相关的代码存储区域

3.栈内存 存储局部变量,变量运算区域一结束,就释放

4.堆内存 存储的是数组和对象,简单说,堆内存存储的都是实体(能存储很多数据的地方就是

实体)

new出来的都存放在堆内存

5.方法区 存储函数的地方(或者说存储共享数据的地方)

14:imageLoader的理解以及它和其他的类似的图片加载有什么不同?

1.里面的防止内存溢出的算法,如果超过limit,就遍历吧集合中的图片删掉,

还有lruCache用的是linkedHashedmap集合,去remove,get;

2.如果图片很大,超过limit时,就压缩,用一个永真循环,去动态改变压缩比例的因子;

15.gallery用过吗:

和listview类似,使用适配器,填充图片即可;

16.adapter作用和常用的那些adapter;

作用:为容器提供子视图,利用视图的数据和view来构建每个子视图。

arrayAdapter ,simpleCursorAdapter, cursorAdapter resourceCursorAdapter

16.intent,service,activity的区别

1.Intent: Intent的调用是用来进行UI之间的切换的,封装了动作和动作对应的数据;

2.Service:服务,具有一段较长生命周期且没有用户界面的程序。Service在后台运行,不

可交互,不能自己运行,需要通过Activity或者其他Context对象来调用,有

Context.startService()和Context.bindService()两种方式启动. Service的生命周期:

onCreate、onStart、onDestroy

3.activity:是最基本的android应用程序组件,主要是生命周期的把握,其次就是状态的保

存和恢复(onSaveInstanceState onRestoreInstanceState),以及Activity之间的跳转和

数据传输(intent)。

context:应用程序所有功能可以通过他访问;

17.垃圾回收机制:

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

DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行,都拥有一个独立

的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个

概念。

19、说说mvc模式的原理,它在android中的运用

MVC(Model_view_contraller)”模型_视图_控制器”。 MVC应用程序总是由这三个部分组成

。Event(事件)导致Controller改变Model或View,或者同时改变两者。只要 Controller改

变了Models的数据或者属性,所有依赖的View都会自动更新。类似的,只要Controller改变

了View,View会 从潜在的Model中获取数据来刷新自己。

20.2. GC内存泄露?

出现情况:?

1.数据库的cursor没有关闭?

2.构造adapter时,没有使用缓存contentview?

?? 衍生listview的优化问题-----减少创建view的对象,充分使用contentview,可以使用一

静态类来优化处理getview的过程/?

3.Bitmap对象不使用时采用recycle()释放内存?

4.activity中的对象的生命周期大于activity?

不要保留对Context-Activity长时间的引用(对Activity的引用的时候,必须确保拥有和

Activity一样的生命周期)

尝试使用Context-Application来替代Context-Activity

如果你不想控制内部类的生命周期,应避免在Activity中使用非静态的内部类,而应该

使用静态的内部类,并在其中创建一个对Activity的弱引用。这种情况的解决办法是使用一

个静态的内部类,其中拥有对外部类的WeakReference,如同ViewRoot和它的Winner类那样

另外:内存泄露与内存溢出的区别:

内存溢出:指的是申请的内存不够,

内存泄露:指的是申请内存后,对某些资源没有及时释放,很多内存泄露,最终会导致内存溢出

;

21.IPC及原理

Linux系统中进程间通信的方式有:socket, named pipe,message queque, signal,share

memory。Java系统中的进程间通信方式有socket, named pipe等

IBinder接口

IBinder接口是对跨进程的对象的抽象。普通对象在当前进程可以访问,如果希望对象能被

其它进程访问,那就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远

程对象,调用者不需要关心指向的对象是本地的还是远程。

22.get和post区别:

1.get提交,提交的信息显示在地址栏

post提交,提交的信息不显示在地址栏

2.get提交,对于敏感的数据不安全

post提交,对于敏感的数据安全

3.get提交,对于大数据不行,因为地址栏存储体积有限

post提交,可以提交大体积数据

4.get提交,将信息封装到请求消息的请求行中

post提交,将信息封装到请求体中;

5.服务端区别

出现乱码,先用iso8859编码,在指定中文码表解码,对get和post都有用,但是

但对于post提交的中文,还有一种解决方法,

request.setcharacterencoding(),这种方法只对请求体中的数据有用;

23.状态选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

<item android:state_pressed="true"

android:drawable="@drawable/bind_sim_bg_pressed" /> <!-- pressed -->

<item android:state_focused="true"

android:drawable="@drawable/bind_sim_bg_pressed" /> <!-- focused -->

<item android:drawable="@drawable/bind_sim_bg" /> <!-- default -->

</selector>

24.自定义属性:

1.添加自定义的属性.

2.声明命名空间

3. 声明自定义的属性 自定义样式 values下新建attrs.xml文件

4.TypedArray ta = context.obtainStyledAttributes(attrs,

R.styleable.MySettingView);

25:Android保存数据的方法有5种,

sharedperference存储,File文件存储,sqlite数据库存储,contentprovider存储,网络存储,

26.activity之间传递数据的方法有哪些?

1.Intent对象

传输数据仅限简单数据和实现序列话的对象。

2.静态变量

将需要共享的对象或者数据声明为静态,可以传递任何类型的数据

3.剪切板

可以利用Android自带的剪切板功能传送数据

传递数据

Intent intent=new Intent(this,MainActivity.class);

ClipboardManager cliper=(ClipboardManager)getSystemServer

(Context.CLIPBOARD_SERVER);

cliper.setText("message");

startActivity(intent);

接收数据

ClipboardManager cliper=(ClipboardManager)getSystemServer

(Context.CLIPBOARD_SERVER);

String str=cliper.getText().toString();

4.全局对象

为每个应用程序定义一个全局的对象,该对象创建由系统负责,使用全局对象需要继承

android.app.Application类,可以在该类中定义任何方法。

package com.example.transmitdata;

import android.app.Application;

public class mAPP extends Application(){

public String str;

public Data data;

}

然后需要在AndroidManifest.xml文件中定义该类

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android ="http://schemas.andoid.com/apk/res/android"

package="com.example.transmitdata"

<application android:name=".mAPP "

......

/>

/>

可以在程序任意位置获取mAPP对象。

mAPP mapp=(mAPP)getApplicationContext();

面试官问:activity之间传递一个大的图片怎么传:

只能是用文件把图片存储,再在另一个activity中在获取;

5 基于Ipc的通信机制

context与service之间的传输,如Activity与Service之间的通信

6.基于外部存储的传输 ,File/Preference/Sqlite,如果要针对第三方应用需要Content

provider

1.简要描述对Static关键字的理解;

Static静态的,随着类的加载而加载,生命周期为进程的生命周期;

同一个类中的static变量在内存中只会有一份,不同对象共享,

static方法相对普通方法调用速度更快,一般工具类的方法都是static

static的调用可以直接用类调用,而不必创建对象;

2.简要描述java中内存回收机制(gc)的理解;

gc的调用:在内存紧张时,系统会调用gc释放内存并且2.3版本以上gc是异步调用的,也可以手动gc,

gc的原理:系统中有一个GcRoot,gc的时候系统会遍历凡是gcroot可以引用到的均不会被回收,gcroot引用

不到的会被回收,根据这个原理,内存泄漏便是由于长生命周期的对象引用段声明周期的对象导致

短生命周期的无法被回收.

3.java中线程同步的几种方式;

同步方法,与同步锁

同步方法用于在方法上,同步锁要一个对象

线程安全问题:多个线程同事访问一个对象导致数据错乱;

4.请描述Activity的声明周期;

oncreate ,onstart,onresume,onpause,onstop,ondestory,

一般可以在onause或者onstart中做数据刷新的工作;

5.handler机制的原理;

主要是hander thread,looper,message之间的关系;

messagequeue为消息的存储单元,内部为单链表,用于消息的存储.

looper为消费的执行单元,looper.loop()方法中无限循环取出消息执行消息,

handler为消息的发送单元.

looper.prepare和looper.loop()在哪个线程中最终就在哪个线程中调用handler.handlermessage()方法,

handler拿到哪个线程的looper就会拿到对应线程的messagequeue,然后往相应的messagequeue发送消息,

looper.loop()在哪个线程最终hanldermessage就在哪个线程执行,如handlerthread就是子线程中执行.

6.简要描述android中view的绘制机制

onmeasure测量:根据父view传递过来的measurespec和子view的layoutparams形成自己的测量规则测量出自己的大小.

viewgroup会通过measurechild方法一步步从上到下测量出子view的大小.,然后测量出自己的大小,在setmeasuredemension()中设置自身大小;

onlayout布局:setFrame()设置自己的四个顶点坐标,然后调用onlayout测量,设置子view的四个顶点坐标一步步从上到下布局完成;

draw规则:先绘制背景,然后在ondraw中绘制内容,在dispatchDraw中绘制子view最后绘制装饰,dispatchdraw()中完成从上到下的遍历绘制.

7.简要描述androdi中事件分发机制:

从activity,windwo,view

view先判断ontouchlistener是否是null,用ontouch再判断view是否enable如果false则再调用ontouchevent()如果可点击或可长点击则消耗事件.

viewgroup会从最后一个子view开始遍历判断点击坐标是否落在子view区域内和子view是否在做动画如果满足条件调用子view的dispatchtouchevent()

分发成功就把子view设置为target,以后down事件之后的传递都给这个子view,不然调用viewgroup的ontouchenevent()

8.请说出android进程间传递数据的几种方式

intent,bundle,binder,content privder,广播,messager,文件,网络,

9.android dvn的进程和linux进程,应用程序进程是否为同一个概念?

是同一个概念,android启动一个进程就会从母进程中fork一个进程,这个fork的进程就是dvm进程就是linux进程.

10.android中一张40x40像素的图片加载后所占用多大的内存;

如果图片是argb8888的4x40x40=6400字节,和每个像素占用的字节数有关;


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: