Android面试总结

面试准备:
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(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.状态选择器:

              android:drawable="@drawable/bind_sim_bg_pressed" />
              android:drawable="@drawable/bind_sim_bg_pressed" />

   

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文件中定义该类
 

        package="com.example.transmitdata"

        

                 ......
           />
/>
 
可以在程序任意位置获取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字节,和每个像素占用的字节数有关;

 

 


 



你可能感兴趣的:(Android面试总结)