澳门皇冠金沙网站-澳门皇冠844网站

热门关键词: 澳门皇冠金沙网站,澳门皇冠844网站

Android面试基础题总结二,听课笔记

在问题的最右处对问题进行等级评定,层层深入

Android性能优化(高级)

  1. 简述Android的系统架构?

    • android的系统架构从下往上分为Linux内核层,运行库,应用程序框架层和应用程序层。
  2. 如何对Android应用进行性能分析;

    • 使用ddms工具中的traceview,heap,allocation tracker工具。traceview是Android平台特有的数据采集和分析工具,可以用来分析耗时操作等。heap视图工具可以帮助我们检查代码中是否存在有造成内存泄漏的地方,allocation tracker工具是内存分配跟踪工具。
  3. 什么情况下会导致内存泄露;

    • Android的虚拟机是基于寄存器的Dalvik,它的最大堆内存是16M,部分机器是24M,因此能利用的内存空间是有限的,一旦超出就会造成OutOfMemory异常。
    • 内存泄漏的几点原因:1)资源释放问题,程序代码的问题,长期保持某些资源,如context,cursor,io流的引用,资源得不到释放就造成内存泄漏。2)对象内存过大问题,保存了多个耗用内存过大的对象(如bitmap,xml文件),造成内存超出限制。3)static关键字的使用,static在Java中,当用来修饰成员变量的时候,那么该变量就属于该类,而不是该类的实例,因此用static修饰的变量,生命周期很长。针对static的解决方案:尽量避免static成员变量引用资源耗费过多的实例,比如context,context尽量使用ApplicationContext,因为Application的context的生命周期比较长,引用他不会出现内存泄漏的问题。4)线程导致内存泄漏,线程的生命周期不可控。
  4. OOM是什么?应如何避免?

    • 内存溢出,要避免OOM异常需要先知道是什么原因导致的异常,

    • 图片过大导致OOM,在Android中用bitmap很容易导致内存溢出,比如报如下错误:
      Java.lang.OutOfMemoryError : bitmap size exceeds VM budget。

      • 解决方法:

          //1)等比例缩小图片
          options.inSampleSize = 2;
          //Options 只保存图片尺寸大小,不保存图片到内存
          BitmapFactory.Options opts = new BitmapFactory.Options();
          opts.inSampleSize = 2;
          Bitmap bmp = null;
          bmp = BitmapFactory.decodeResource(getResources(),
          mImageIds[position],opts);
          //回收
          bmp.recycle();
        
          //2)对图片采用弱引用,及时的进行recycle()操作。
          SoftReference<Bitmap> bitmap = new SoftReference<Bitmap>(pBitmap);
              if(bitmap != null){
                  if(bitmap.get() != null && !bitmap.get().isRecycled()){
                      bitmap.get().recycle();
                      bitmap = null;
              }
          }
           3)使用图片加载框架处理图片。
        
    • 界面切换的时候导致OOM,一般情况下,开发中都会禁止横屏,一旦横竖屏切换的多了,activity的生命周期就会重新销毁然后创建。切换的次数多了,就会导致OOM。这种问题没有固定的解决方案,可以从一下几方面着手分析,

      • 1)看页面布局中有没有大的图片,如背景图之类的,去除xml文件中相关设置,改在代码中设置(放在onCreate()方法中)

          Drawable drawable = getResources().getDrawable(R.drawable.id);
          ImageView imageView = new ImageView(this);
          imageView.setBackgroundDrawable(drawable);
        
          //在activity  destory的时候注意,要drawable.setCallback(null),防止得不到及时的释放。
        
    • 查新数据库时没有关闭游标。

    • 构造adapter时,没有使用缓存convertView,使用convertView的好处:
      当convertView 为空时,用setTag()方法为每个View 绑定一个存放控件的ViewHolder 对象。当convertView 不为空,重复利用已经创建的view 的时候,使用getTag()方法获取绑定的ViewHolder 对象,这样就避免了findViewById 对控件的层层查询,而是快速定位到控件。

    • bitmap对象不再使用的时候调用recycle()方法释放内存。

    • 使用广播没有注销的时候也会产生OOM。

  5. ANR是什么? 应如何避免和解决?

    • application not responding 程序无响应。ANR一般有三种类型: activity 5秒,broadcastReceiver10秒,services20秒。超时的原因一般有两种:1)当前的事件没有机会得到处理(UI线程正在处理前一个事件没有及时完成或者looper被某种原因阻塞住)2)当前的事件正在处理,但没有及时完成,UI线程尽量只做UI相关的工作,耗时操作(数据库操作,io流,连接网络或者其他可能阻碍UI线程的操作)放入单独的线程处理,尽量用handler来处理UI thread和thread之间的交互。
  6. Android中线程间通信有那几种方式?

    • 共享内存(变量),文件,数据库,handler,Java中wait(),notify(),notifyAll()。
  7. 线程和进程之间的区别?

    • 一个应用程序至少有一个进程,一个进程至少有一条线程,一个线程可以创建和撤销另一个线程,同一个进程中的多个线程可以并发执行。从逻辑角度讲,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行,但操作系统并没有将多个线程看成多个独立的应用,来实现进程的调度,管理和资源分配。

以下内容为慕课网【Android面试】课程的视频整理笔记,同时加上了一些自己的理解,整理较为粗糙,可以根据这个框架再去细致的了解。

1.Android线程之间的异步通信有哪些?

handler.sendMessage AsyncTask View.post Activity.runOnUiThread Loaders等

  • 1-1handler深入,looper,messageQueue是怎么合作工作的

在ActivityThread启动main方法中,会去创建looper对象,并且与主线程进行绑定.一个线程只有一个looper,这个looper管理着自己的messageQueue,创建绑定完之后就进入了无限循环从messageQueue中取消息,只要应用不退出,就无限循环.接着只要我们在主线程中新建handler对象,就会跟创建该handler的线程的looper绑定(在handler的构造函数中),之后looper负责将handler send出来的message加入到queue的尾部,然后再由looper负责将message从queue的头取出(经过loop方法中的dispatchMessage进行消息分发),执行handleMessage.

1-1-1可以直接在线程中直接new一个handler出来使用么?要注意什么呢?如果不注意会报什么错误呢?

在子线程中创建handler的时候一定要注意创建的时候需要同时去创建looper,否则会由于在子线程中没有绑定的looper对象而报错.报错无能直接在子线程中建立handler的错误.

1-1-2android在启动了之后为什么可以直接在activity中new一个handler进行使用呢

因为在ActivityThread中系统已经帮主线程创建并且绑定好了looper,这个时候只要new一个handler,在handler的构造函数中就会自动的将handler自身与looper进行绑定

  • 1-2asynctask是怎么使用的呢?怎么构建,方法怎么调用?三个参数传入的分别是什么呢?

自定义后通过new出来对象,执行对象的excute方法实现. 常见的方法onPreExecute和onPostExecute分别在doinbackground方法前后执行,doinbackground负责在子线程中执行任务,然后将结果交由onPostExcute在主线程中处理,同时可以由onProgressUpdate来进行实时的将处理状态返回给主线程处理.定义时的三个参数,依次为传入的参数类型;第二个参数为后台处理的进度显式类型,是int还是float还是其他;第三个参数是doinbackground执行之后return给onPostExecute接受的结果类型.

1-2-1asynctask在使用的过程中哪些方法可以进行UI操作呢?

直接去AsyncTask中去看有MainThread标注的都是可以在主线程中执行的onPostExecute onProgressUpdate onPreExecute onCancelled 其实都可以讲的通

1-2-2asynctask的最高同时执行线程数,可以改么?怎么改?

在3.0以前,支持并行处理,也就是说同时可以执行多个任务,当时是写死的线程池,同时可以处理的最大线程数为5个,线程池大小位128,如果同时添加超过128个AsyncTask任务,那么系统就会崩溃.3.0之后改成了串行处理,同时只能处理一个任务.其实不然,其实3.0之后变得更加灵活,可以自己去定义Executor

Executor exec = new ThreadPoolExecutor(15, 200, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>; new DownloadTask().executeOnExecutor; 

传入的三个参数分别表示,可并行执行的最大的线程数,线程池大小,和超过内核数的线程最多可以存活的时间(比如我们有10个线程,内核数为4核,那么多下来的6个线程,最多可以存活如上所述的10秒)

1-2-3asynctask的弊端,

  1. 使用cancel方法时无法直接停止子线程,由于调用了cancel方法会去调用子线程的interrupt方法,但是这个方法不会直接停止子线程而是只是更改一个标志位,具体的停止操作需要用户在线程中自己做监听.所以oncancel的真正起作用的只不过是不会去调用onPostExecute
  1. onPostExecute的时候回调出来,activity或者fragment对象已经被销毁的话就会出现找不到对象的错误.这个时候要么做空判断,要么自己定义抽象类BaseAsyncTask复写onPostExecute,并final它
  2. 内存泄露,在activity的匿名内部类AsyncTask,由于AsyncTask的生命周期和activity不同步,当activity被销毁的时候,可能asynctask还在执行,那么后者持有的前者对象就会难以释放,导致内存泄露.
  3. 当asynctask在执行的时候,activity由于屏幕旋转或其他原因导致重建,asyncTask由于持有的是之前的activity的引用,就会导致onPostExecute的代码不起作用.
  • 1-3 主线程阻塞超过几秒出现ANR,数据库阻塞呢?广播接受阻塞呢?

主线程5秒未响应,数据库10秒,广播10秒未相应,会出现ANR

  • 1-4 View.post可以执行耗时的操作么?为什么?

不可以执行耗时操作,View.post出来的runnable是在UI线程中执行的.

android的屏幕适配 :

  1. 屏幕适配的方式有哪些?

    • 适配方式有:权重weight适配,layout适配,代码使配,dp适配(layout中定义布局设置的参数使用dp),dimens适配。
    • 在values-1280x720目录中的dimens。xml文件中定义同样的尺寸名称,但是使用不同的尺寸,当在布局文件中使用长或宽单位时,用@dimens/width来定义。如果在values-1280x720中放置了dimens常量,一定要记得将该常量的对应值在values目录中的dimens.xml中也放一份,因为该文件是默认配置,当用户的手机不是1280*720的时候,系统应用用的是默认values目录中的dimens.xml。
  2. 屏幕适配的处理技巧?

    • 在分辨率大小不同的问题上,推荐使用权重weight适配,一般应用于线性布局中。
    • 尽量使用线性布局,相对布局,如果屏幕放不下数据,可以使用ScrollView来拖动。
    • 尽量使用9-patch图片,可以自动的根据图片上面显示的内容被拉伸和收缩。

内容为一到四章。

五到九章参见

慕课网【Android面试】听课笔记(二)

2.平时在使用listview的时候都会注意哪些问题?

图片的异步加载方面,性能优化方面(ViewHolder, convertView,滑动的时候不加载图片等)

  • 2-1在listview中需要加载图片的话有什么比较好的方法么?

采用异步加载的方式,当然可以使用第三方的图片库picasso,fresco,也可以自己实现.

2-1-1 知道怎么去写一个imageloader么?

简易的imageLoader负责图片的异步加载,方法可以不止一个.将图片的url设置为view的tag,将view传给imageloader,imageloader本身管理着一套lru缓存,将url取出后,先去缓存中查看是否有该图片,有的话直接回调显示,没有的话进行网络请求,得到结果候进行网络显示并做本地缓存.如果加载失败则显式失败的画面的.

2-1-2 有哪些第三方好用的图片库,看过源码么,可以讲一讲么,区别,推荐

picasso, fresco, glide, Universal-image-loader如果预见项目中会有很多圆角或渐进式JPEG等需求,可以使用Fresco;如果是老项目已经使用了UIL或者Picasso,且依赖较多不容易修改,则可以继续使用;如果还在纠结如何避免65K方法数,推荐使用Glide代替Fresco 因为Glide比后者实在轻巧了太多;如果是老项目需要换加载库,推荐使用Glide而不是Fresco, 降低迁移工作量;如果是新项目,不推荐使用已经停止维护的UIL,也不推荐Picasso,推荐使用Glide;

  • 2-2 如果使用过程中出现了不同的item需要展示不同的布局,这个时候用什么方法解决?

使用listView的viewtype去区别不同的展示

  • 2-3 listview怎么去和数据库做绑定呢?

使用cursorAdapter去实现和数据库的绑定

2-3-1 如果想要listview对数据库做实时的更新,会怎么做呢?

使用cursorLoader绑定listview,用观察者模式对数据库进行监听,一旦有变化,swapcursor,并notifyDataChanged

AIDL

  1. 什么是ALDI?应如何使用?

    • AIDL是android interface definition language 意思是Android接口定义语言。使用aidl可以帮助我们发布以及调用远程服务,实现跨进程通信。
  2. AIDL如何工作,能处理哪些类型数据?

    • 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程跨进程对象访问的目的,需要完成两件事:一是引入aidl的相关类;二是调用aidl产生的class文件,理论上,参数可以传递基本数据类型和String,还有就是Bundle的派生类。

一、课程简介

  • 基础知识

    • Fragment
    • Activity
    • Service
    • 广播
    • Binder
    • Webview安全漏洞
  • 异步消息处理

    • Handler
    • IntentService
    • AsyncTask
    • HandlerThread
  • View相关

    • View渲染和绘制
    • 事件分发
    • ListView优化
  • Android构建

    • 编译打包
    • Gradle
    • Proguard混淆
    • 渠道包
    • Git
  • 开源框架

    • 网络框架:Retrofit,Okhttp,Volley
    • 图片:Glide,Fresco,UIL
    • IOC:Dagger3 ButterKnife
  • 热门前沿

    • 插件化
    • RxJava
    • 热更新
    • 进程保活

--

3. 有使用过自定义控件么,自定义控件从定义到使用,怎么个流程,可以粗略的讲一下么

  1. 首先我们需要去attr.xml文件中去定义我们控件中需要的一些自定义的属性.
  1. 然后创建我们自定义的控件继承View,主要好复写onDraw,onLayout,和onMeasure方法,以及它的构造函数.
  2. onMeasure中根据传入的宽高mode,来选择是否要对控件进行计算.如果是wrap_content的则将控件的宽高计算出来setMeasureDimension
  3. onLayout,经过计算过后的measure宽高来获得控件的坐标点,导入onLayout
  4. 最后在onDraw方法中,利用画布画笔对需要的背景或者其他内部元素进行绘制.
  5. 在布局文件中,添加自定义view,与自定义命名空间,来使用该自定义控件的属性.
  • 3-1 如果我需要为这个自定义控件创建一些特有的属性,比如说想要在布局文件中控制它的字体大小,字体颜色,应该怎么去做?

在attr文件中定义自定义属性,然后在自定义控件的构造函数中通过TypeArray取出,然后对其遍历index,取出属性值,做相应处理.

  • 3-2 除了使用动画之外,还有什么方法可以实现一个动态的view?

可以使用surfaceView

3-2-1 surfaceview和一般的view有什么地方不同?

一般的view都是在主线程中进行绘制的,而surfaceView是独立线程进行绘制,因此可以进行复杂的绘制,不会阻塞主线程.

3-2-2 你觉得什么情景中会使用到surfaceview,或者你知道什么地方会用到surfaceview

相机模块中会使用到,或者是复杂的动画显示,或者是一些游戏界面也会食用到,只要是画面在不断的变化的就可以使用surfaceView去实现.

3-2-3 在使用surfaceview的时候需要注意一些什么?什么时候画,什么时候不画?怎么去做

注意启动和关闭绘制.由于它的特殊性,我们可以在onResume中启动绘制,在onPause中停止绘制.由于自定义的surfaceView需要去实现runnable,在类内部实现其run方法,我们可以设置一个标志位,在run方法中进行循环判断,一旦标志位为false就停止绘制,然后可以在view的onPause和onResume中修改标志位.

android 的事件处理 :

二、 技术要求及面试前准备

良好的开发习惯;独立思考的能力;主动并善于沟通;

招聘要求例子
1.常用设计模式及数据机构;(手写算法,加分点)
2.Android开发经验;
3.Java语言基础;(java的高级特性)
4.网络编程,性能优化,内存优化;

高级工程师要求
1.基本知识点
2.深入知识点
3.基本知识点的细节
4.系统核心机制

开口去说,事先预演,说的时候才知道问题所在,有条理。

面试中要求:
1.礼貌,态度谦虚;
2.听懂问题直接回答;

感悟
基础知识,看简历面试,根据公司需求,看你牛不牛;

1.选一个擅长的领域,如网络框架;
2.基础要背,灵活的背诵,背诵常用API;
3.了解领域前沿技术;
4.研究一个熟悉库的源码;

4.有没有NDK编程经验,或者说对NDK有了解么?

结合C或C ,进行android编程,一般使用比较多的是方法封装,编译成so库文件,供android项目使用.

  • 4-1 讲一下NDK的一个大体流程,或者说现在给你一个工具类,如何去调用C代码的一些方法?
  1. 首先需要使用NDK生成相应的头文件,或者是自己写也行.然后新建.c文件,引用该头文件,然后注意定义的与java交接的方法名需要与调用该方法的类的包名相同,要遵循相应的规则.
  1. 然后在c文件中,实现该方法.之后在gradle中对其进行配置.执行NDK编译,在build目录下得到相应文件夹的so文件,将so文件放入jniLib中.
  2. 在工具类中静态加载so库,然后调用相应方法即可生效.
  • 4-1-1 eclipse上的NDK编程和studio上的有什么不同?

eclipse上需要通过Android.mk和application.mk去对该NDK项目进行配置,而在studio上直接在gradle中进行配置即可.

handler消息机制:

  1. Android中主线程主要是用来创建,更新UI的,而耗时操作,网络请求等则需要在子线程中操作。而handler主要接受子线程发送的数据,并用该数据来配合主线程更新UI,handler运行在主线程中,他和子线程通过message对象来传递数据(子线程通过sendMessage()方法来发送消息,数据),将子线程发送来的这些消息放入到主线程中,配合主线程来更新UI。

  2. handleThread,Looper,MessageQueue和Message的关系:handlerThread负责将需要传递的信息封装成Message对象,通过handler对象的sendMesage()方法将消息传递给looper,在有looper将message放入messageQueue消息队列中,当looper对象看见MessageQueue中含有Message时,就将其广播出去,该handler对象手到该消息之后,调用相应的handler对象的handlerMessage()方法对其进行处理。

  3. handler消息机制的底层简单分析:

    • 首先是messageQueue和Looper的创建:当系统启动的时候,先加载activityThread这个类,在这个类中的main方法会调用Looper.prepareMainLooper()这个方法,来创建一个Looper对象,Looper对象就会通过ThreadLocal把他和当前线程绑定在一起,创建Looper的时候就创建了一个MessageQueue,MessageQueue是个final类型的成员变量。这样就保证了一个Looper对应一个MessageQueue,所有的MessageQueue创建好了之后,就会一个线程对应唯一的messageQueue。然后MessageQueue在创建的时候通过JNI创建了一个NativeMessageQueue,他又创建了一个c Looper,所以说Handler的底层是通过C 来实现的。MessageQueue中保存了一个int类型的成员变量mptr,他保存了NativeMessageQueue的指针,这样就是了MessageQueue和NativeMessageQueue的对应。
    • 接下来是从消息队列中取消息:之后就会调用Looper.loop()来取消息,这里面有一个死循环,在这个死循环里存在着queue.next();的方法他是阻塞主线程的,它实际上就是调用了NativeMessageQueue去C 层取消息,如果取出来这个loop就去执行,没取出来就会阻塞在这里不去执行,这样就能是界面能够停留而不至于代码执行完界面就跳出;取出消息后调用handler.dispatchMessage()来分发消息,message这里面有一个回调,handler在创建的时候有一个回调,如果两个回调都为空的那么直接调用handleMessage()来处理消息,这就是取消息。
    • 最后就是存消息:也就是向消息队列中发送消息,不管是sendMessage还是sendMessageDelaty等他们调用都是sendMessageAtTime(),在这个方法里面他实际调用的是messqueue.enqueuemessage()这里面实际上就是拿着当前消息要执行的时间进行排序,然后就会通过消息队列保存起来,这里面有一个message.next()他们都可以通过这个方法一条指向下一条,这样一条一条连起来,当有消息需要马上执行就会调用nativewake(),这个方法就会把Looper.looper()的queue.next()唤醒就能取出消息,他就可以开始工作.

三、基础相关面试题

5. 对当今比较流行的框架有了解么?可以举出你知道的一些框架么?

网络框架 retrofit,Okhttp,volly等 缓存DIskLruCache等 数据库OrmLite,GreenDao等, 依赖注入Dagger2 butterKnife等 事件总线 eventBus等 RX响应式编程 内存泄露LeakCanary等等有很多

  • 5-1 看过框架的源码么?讲一下框架大概原理,是怎么工作的?

看具体回答评级

  • 5-2 知道RN,听说过热修复么?动态加载,插件化知道多少?

reactive-native利用js, html, css重新定义一套规则, 编写原生的ios,android移动应用.hotfix,利用动态加载技术,在用户手机崩溃时,调用远程服务端的可执行文件,待远程将问题解决了之后,现场修复,替换掉有问题的坑,再让手机执行修复后的本地文件,避免了频繁的版本更新.比较热门方案的有AndFix, DexPosed, ClassLoader.热门的实现有Nuwa,HotFix,DroidFix.而动态加载和插件化开发可以方便大规模团队协同开发, 技术也应用于热补丁修复,将项目开发模块化分散.内容比较多,上面也只是个大概,具体看怎么去回答,根据回答的详细情况,了解情况来进行评级.

事件分发机制

  1. OnTouchEvent的事件传递机制:

    • 当手指触摸到屏幕时,系统会调用相应的view的onTouchEvent,传入一系列的action,那么首先触发的是activity的dispatchTouchEvent,然后触发activity的onUserInteraction,在触Layout的dispatchTouchEvent,然后触发Layout的onInterceptTouchEvent.

    如果dispatchTouchEvent:
    事件由此分发,通常会调用super. DispatchTouchEvent.
    如果onInterceptTouchEvent(拦截事件):
    返回true:表示事件被拦截会传递给自己的onTouchEvent处理,
    返回false:不进行拦截,会将事件传递给下一个view的dispatchTouchEvent()进行判断.
    如果onTouchEvent:
    返回结果为true:表示事件由自己处理,消费.
    返回结果为false:表示当前事件自己不做处理,交给父view的onTouchEvent处理.

3-1 Activity面试详解一

6.对整个手机的布局有了解么?画一下整个的手机布局框架

观察是否有phoneWindow和decorView的概念

  • 6-1 Activity,View,Window的关系是什么?

我们在activity的attach方法中,会去生成window,就是整个手机的最根的布局,而这个window的实现类是phoneWindow,在phoneWindow中有一个最顶层的视图DecorView, 由phoneWIndow将布局文件进行解析,然后将相应的view加载到DecorVIew中.

  • 6-1-1 setcontentView到底是怎么样把布局文件让手机屏幕展示出来的

phoneWindow得setContentView方法来将activity的setContentView的布局文件加载到视图中去,这就是这三者的关系。实际上直接看setContentView的源码实现就知道它调用了getWindow().setContentView()再点开发现是空实现,因为真正的实现就在phoneWindow中。

view的绘制流程:

参考博文:http://www.jianshu.com/p/5a71014e7b1b
  1. 子线程发消息到主线程更新UI,处理handler,asyncTask还有什么;

    • 用activity对象的runOnUiThread()在线程中更新UI。

        new Thread() {
        @Override
        public void run() {
        super.run();
        //这儿是耗时操作,完成之后更新ui.
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //更新ui
                ImageView.setImageBitmap(bitmap);
            }
        });
        }
        }.start();
      
            //如果是非上下文类中(activity),可以通过传递上下文实现调用;
            //Activity activity = (Activity) imageView.getContext() ;
      
         activity.runOnUiThread(new Runable() {
          @Override
          public void run() {
            imageView.setImageBitmap(bitmap);
            }
         });   
      
  2. 子线程中能不能new handler,为什么?

    • 不能,如果在子线程中直接new Handler() 会抛异常。

1.Activity的四种状态

running,
paused, 弹出对话框
stopped,完全被覆盖
killed:被回收掉了

7. 四个lunchmode

standard,singleTop,singleTask,singleInstance

  • 7-1 分别介绍一下使用场景

singleTop 直接吊起activity栈的最顶部activity。 点击通知推送需要进入到一个界面,那么如果收到多个推送的话,停留在这个界面去点击这个推送就不用再去重新生成这个界面activity。singleTask 启动activity栈中的该activity,并把其上的所有activity清空。 一般用在程序的入口,比如从好几个应用启动了浏览器,只会启动浏览器的主界面一次,浏览器主界面之后的activity都会清空掉。singleInstance 特地为个别activity单独建立一个activity的栈,多次重复利用。 某个应用中用到了google地图,当退出该应用再次进入google地图的时候,还是停留在刚才的画面。** **

  • 7-2 使用singleTask时候会遇到什么问题么?比如用startActivityForResult去调用singleTask的activity会出现什么现象呢?

启动singleTask和singleInstance这两类模式的activity的时候,需要注意不要去用startActivityForResult方法调用,回立马收到cancel的回调.

  • 7-2-1 那么singleInstance呢?

  • 7-2-2 如果A真的想要用startActivityForResult去启动singleTask的B的话怎么办?

直接在B中再将需要回传的数据通过startActivty的方式去启动A.

Android 中的动画 :

  1. 动画类型有几种,特点和区别是什么?

    • 属性动画,补间动画;补间动画只是显示的位置变动,view的实际位置未改变,表现为view移动到其他地方,点击事件仍在原处才能相应,而属性动画在控件移动后时间响应就在控件移动后本身进行处理。
  2. 如何修改Activity进入和退出的动画;

    • 通过两种方式:1)通过定义activity的主题,2)通过复写activity的overridePendingTransition(R.anim.fade,R.anim.hold)方法。

2. Activity生命周期

启动:onCreate->onStart->onResume
onStart:可见 ,但是不能交互;
onResume:可见,可交互;

点击Home,返回主页面:onPause->onStop

onPause:可见,暂停
onStop:被完全覆盖

点击重新回到app:onRestart->onStart->onResume
退出:onPause->onStop->onDestroy

8. 大体讲一下触摸事件分发吧

隧道式的分发,冒泡式的反馈,一路直接到可以处理触摸事件的view,然后一路向上按照分发下来的路径反向反馈。最外层的布局调它的dispatchTouchEvent方法,在方法中会去看能否拦截,如果可以且需要拦截那就拦截不往下传递,否则的话遍历找到符合条件的子view去调用它的dispatchTouchEvent,知道最终消费处理这个点击事件的子view的dispatch方法返回true,然后就不往下传递,并往上走出这个递归,这就是viewGroup和view之间的事件分发机制,结合view自己的分发就可以完美解答这个问题。

  • 8-1 intercept返回true,false分别表示什么意思?dispatchTouchEvent呢?onTouchEvent呢?

intercept返回true表示拦截了,onTouch返回true表示被我监听器消耗了,onTouchEvent表示被我view自己吃了,然后dispatchTouchEvent表示被我这个view处理消耗了。总的来说就是返回true代表不往下继续传递,开始往上传递了.

  • 8-2 onclick, ontouch,ontouchevent的执行的顺序是什么?你是怎么知道的

一段源码告诉你,在View的dispatchTouchEvent中,onclick是写在onTouchEvent中的。

图片 1

所以正确的顺序应该是onTouch ----> onTouchEvent --------> onClick

LRUCache的底层原理:

  1. 通过获取内存的最大可用值,lrucache通过构造函数传入缓存值,它是kb为单位,在不超出可使用内存的最大值的情况下,超出就会OOM,通过使用最大缓存值的1/8作为缓存的大小,重写sizeOf()方法来返回每一张图片的大小,这就是lurcache的是使用方法,那么lruchche为何这样强大,原因是它的主要算法原理是将最近最少使用的对象用强引用存储在LinkedHashMap中,并且将最近最少使用的对象在缓存值达到预设值之前从内存中移除,在过去经常使用一种非常流行的缓存技术实现,就是软引用和弱引用,但现在不再使用了,因为在Android2.3之后。垃圾回收机制更容易倾向于回收持有软引用和弱引用的对象,这就让软引用和弱引用显得不可靠,另外在Android3,0之后,图片的数据会存储在本地内存中,因而无法用一种可预见的方式将其释放,这就会潜在的造成应用程序内存溢出或者崩溃,而再有了lruCache这个功能之后,解决这些问题就不在难了。

3. 进程优先级

参考文章:

android 进程优先级

前台进程:正在交互的进程,或者处于前台的service进程;
包含以下组件的进程属于前台进程:

  • 处于前台正与用户交互的Activity
  • 与前台Acitity绑定的Service
  • 调用了startForeground()的Service
  • 正在执行onCreate(),onStart()或者onDestroy()方法的service
  • 正在执行onReceive()的BroadcastReceiver

前台进程优先级很高,基本不会被杀死。

可见进程:处于可见,但是不是交互;
以下进程属于可见进程:

  • 进程中包含了出于paused状态的activity(弹出了对话框)
  • 进程中包含了与可见进程绑定的Service

服务进程:包含了已启动的服务的进程

后台进程:前台进程按下home键切换到后台 内存不足时,容易被回收

服务进程的优先级高于后台进程,所以可以在服务中开启线程做一些耗时的操作。

空进程: 优先级最低,容易被回收,保存它的唯一目的是为了缓存一些启动数据,以便下次更快的启动应用

9. android的跨进程通信知道那些?

  activity的startActivity方式,activity可以直接通过filter去启动其他应用中定义了intent-filter的activity,然后进行跨进程通信
  content provider的跨进程共享数据  广播的被动跨进程通信  AIDL的binder机制。 
  • 9-1 单单从耦合度分析,广播机制和binder机制有什么不同呢?

广播的发送者和接收者互相都是不知道对方的,而binder则不同,相比前者耦合度更低,可拓展性更强.

9-1-1 广播的静态注册和动态注册分别是怎么实现的呢?有什么不同呢?

静态注册是在androidManifest文件中进行receiver注册,设置相应的intentfilter的action;动态注册直接在代码中进行receiver注册.不同的地方在于动态注册的广播可以进行unRegister,且退出应用了之后就不会再接收到广播,但是静态注册的广播即使退出了应用还是会收到广播.

JNI的调用过程:

  1. 安装和下载cygwin,下载Android NDK.
  2. ndk项目中JNI接口的设计,
  3. 使用C/C 实现本地方法
  4. JNI生成动态链接库.so文件
  5. 将动态链接库复制到Java工程,在Java工程中调用,运行Java工程即可。

3-2 Activity面试二

10. 移动端的网络优化,想的到哪些?

连接复用:默认情况下,httpurlconnection都是开通了keep-alive的功能的合并请求:对于界面中出现频繁请求的情况,可以将请求进行合并,一次性请求。请求压缩: post请求,请求的body或者是header都可以进行gzip压缩; 对于返回数据的格式相差不是很大的,也可以对key部分进行压缩。根据用户的网络质量,判断下载什么质量的图片。本地还可以做静态缓存。直接访问IP,而非域名: 使用动态的IP列表,直接访问IP,一旦IP不能访问了,再用域名进行访问。增量更新:对新增的数据进行更新,bsdiff和bspatch预连接和预取数据:对请求分优先级

图片加载框架picasso,glide,imageLoader,Fresco之间的区别:

  1. 共同的优点:

    • 使用简单--都可以通过一句代码实现图片的获取和显示。
    • 可配置度高,自适应行性高--可根据系统性能初始化缓存配置,给句cpu核数确定最大并发数,根据网络状态变化来调整最大并发数,根据可用内存确定最大缓存大小,
    • 多级缓存--每种框架至少有两级缓存,可以提高图片的加载速度。
    • 支持多种数据源--网络,本地,资源文件。
    • 支持多种displayer--不仅支持imageView,同时支持多种view以及一些虚拟的imageview。
    • 支持动画。

1. 任务栈

任务栈和启动模式息息相关
flag:

  • FLAG_ACTIVITY_NEW_TASK 对应android:launchMode="singleTask"模式,通常在service中启动一个acitivity时,需要加该flag,否则会报错;
  • FLAG_ACTIIVTY_SINGLE_TOP 对应android:launchMode="singleTop"
  • FLAG_ACTIVITY_CLEAR_TOP 与在清单文件指定android:launchMode="singleTask"效果相同

11. service知道多少,一个service从定义到使用大体讲一下?

Service是由framework层的ActivityServiceManager管理的生命周期长、运行于后台的服务性组件。Service本身是运行在当前应用进程的主线程中,但是可以在Service中开辟子线程以实现音乐播放、数据库交互、文件操作等耗时操作(因为绝大多数情况下Service没有前台界面)。需要在manifest文件中声明service的启动有startService和bindService两种方式,前者当应用退出时,依然可以运行,除非调用了stopself或者是系统调用了stopService,而后者则是通过unbindService解绑.oncreate方法只会执行一次,但是每次调用都会执行onStartCommand(startService)/onBindSerivce(bindService0,当调用了stopSelf或者是stopservice之后如果又绑定就执行onUnBind,否则就直接执行onDestory方法.onstartCommand根据具体的返回值来判断service被kill了之后如何重启service.那么综上,

  1. 自定义的service继承service,我们可以通过具体的需求选择是复写它的onStartCommand方法还是onBind方法去实现.
  2. 去清单文件注册service
  3. 通过startService的方式或者是bindService的方式来实现.startService直接启动service,bindService则需要传入ServiceConnection接口,我们可以在接口方法onServiceConnected中去做逻辑处理,或者自定义处理或者将IBinder取出做处理
  • 11-1 service和应用是在一个进程中么?本身是一个线程么?

本身既不时线程也不是进程,service是在主线程中进行的.

11-1-1 intentService和service有什么不同呢?

intentService不用去起新线程就可以执行耗时的操作,内部是利用handler来处理源源不断的intent请求,将intent加入队列,然后依次进行处理.所以在intentService中我们只需要去实现onHandleIntent方法就可以了,而service是在主线程中进行的,需要去另起线程才可以处理耗时的操作.intentService需要定义一个构造函数,在构造函数中调用super方法,传入该服务的名字,来给intentService命名,因为intentService不需要在manifest文件中注册.

11-1-2 intenService内部源码看过么?它是如何做到不用新起线程就可以去执行耗时的操作的?

实际上就是looper的原理。我们进它的源码看一看:

图片 2

新起一个线程,获得它的looper,创建相应的handler这样他就通过handler去不断的循环新扔进来的intent,然后进行处理。所以在intentService中,我们可以直接在onHandleIntent中处理耗时任务。

imageLoader的设计模式:

* 一个强大的图片加载框架,很好的处理了图片加载的多线程,缓存,内存溢出等问题。多线程异步加载和显示图片(图片来源于网络,sd卡,assets文件夹,drawable文件夹,不能加载9patch图片,可以加载视频缩略图)
* ImageLoader 收到加载及显示图片的任务,并将它交给 ImageLoaderEngine,ImageLoaderEngine 分发任务到具体线程池去执行,任务通过 Cache 及 ImageDownloader 获取图片,中间可能经过 BitmapProcessor 和 ImageDecoder 处理,最终转换为Bitmap 交给 BitmapDisplayer 在 ImageAware 中显示。
* imageloader的优点:
* 
    * 支持下载进度条监听,支持在view的滚动中暂停图片的加载,实现了多种内存缓存算法,支持本地缓存文件名规则定义。
    * 支持监视加载的过程,可以暂停加载图片,在经常使用的listview,GridView,可以设置滑动时暂停加载,停止滑动的时候加载图片。
    * 高度可定制化,可以根据自己的需求进行各种配置,(线程池,图片下载器,内存缓存策略等)
    * 支持图片内存缓存,文件缓存
    * 在网络速度较慢的时候,还可以对图片进行加载并设置下载监听。
    * 避免同一个uri加载过程中重复开启任务加载
    * 减少加载大图片出现oom的情况。
    * 不足:
    * 
        * 不支持加载GIF图片。

2. 启动模式

activity的复用

1.standard: 每次启动都会重新创建,不管是否存在;
2.singleTop: 栈顶复用模式,在栈顶时,则不会创建,但是仅仅只是在栈顶;
3.singleTask:栈内复用模式,单例,检查整个栈;onNewIntent;
4.singleInstance:整个系统只有一个实例,打电话

12. 碰到过哪些异常,讲一讲。

Can not perform this action after onSaveInstanceState在Activity保存了状态之后,再对fragmentManger进行commit事务的操作就会造成这个错误,一般最省力的办法就是把commit改成commitAllowStateLoss NetWork on main thread在主线程中进行网络请求 ClassCastException类型强转错误 IndexOutOfBound数组越界 outOfMemory

Picasso的设计模式:

* Picasso 收到加载及显示图片的任务,创建 Request 并将它交给 Dispatcher,Dispatcher 分发任务到具体 RequestHandler,任务通过 MemoryCache 及 Handler(数据获取接口) 获取图片,图片获取成功后通过 PicassoDrawable 显示到 Target 中。
* Picasso的优点:
* 
    * 自带统计监控功能--支持图片缓存使用的监控,包括已使用内存大小,节省的流量。
    * 支持优先级处理。
    * 支持延迟到图片尺寸计算完成加载,
    * 支持飞行模式,并发线程数根据网络类型而变。
    * 无本地缓存--不是说没有本地缓存,而是Picasso自身没有定义本地缓存的接口,默认使用http的本地缓存。

* 不足:
* 
    * 不支持加载GIF图片,缓存之后的图片没有进行缩放

3.scheme跳转协议

通过定义scheme语法实现跳转:

  1. app内页面跳转;
  2. 通过H5页面跳转到app;
  3. 从一个app到另一个app;

13. 不同的屏幕分辨率,如何去适配呢?

最常用的方法是用不同的分辨率文件夹,保存不同分辨率的图片到相应的文件夹下,对于单色图标来说,最好的方法是使用矢量图来解决,既可以适配不同分辨率,又可以帮apk瘦身。在布局方面,我们尽可能的去使用relativelayout,强调的组件和组件之间的位置关系,避免了直接将大小写死,可以很好的适配不同的分辨率,最新的android.support.constraint.ConstraintLayout更是将其发挥到极致。或者我们也可以为不同的屏幕做不同的布局,放在相应layout文件夹下。

  • 13-1 知道那些layout,和drawable文件夹?

图片 3

各尺寸

  • 13-1-1 hdpi和mdpi哪一个大一点

hdpi..

glide的设计模式:

* Glide 收到加载及显示资源的任务,创建 Request 并将它交给RequestManager,Request 启动 Engine 去数据源获取资源(通过 Fetcher ),获取到后 Transformation 处理后交给 Target。Glide 依赖于 DiskLRUCache、GifDecoder 等开源库去完成本地缓存和 Gif 图片解码工作。
* glide的优点:
    * 支持多种图片缓存,GIF,webP,缩略图,甚至是video。
    * 支持优先级处理
    * 支持velloy,okHttp.实际上imageloader。Picasso也支持velloy,OKHttp。
    * 内存缓存的是处理之后的图片,而不是原始图片,节省内存大小。

3-3 Fragment面试一

参考文章:

Android Fragment 真正的完全解析(上)
Android Fragment 真正的完全解析(下)

14. 内存泄露的原因知道哪些?

集合类只知道添加,而没有做好具体的删除工作的话,那么如果遇到全局的集合变量,就会导致这个集合所占用的内存只增不减单例模式一般见得最多的就是写的一些util类,为了需要展示或者是做一些需要context的有关操作,就需要传入context,而为了让Util可以直接进行方法调用,就会将一些方法写成static,然后本类的context对象不得不定义为static,就不得不去静态持有外部的对象,这样以来,当外部对象已经不可到达了之后,由于被这个util持有,依然无法回收,就泄露了。Android特殊的组件需要手动的去关闭比如BroadCastReceiver,ContentReceiver,FileObserver,Callback什么的都需要在onDestory方法或者在activity的生命周期结束的时候回收,否则activity会被系统强引用,无法回收。handler只要handler中的message没有被处理完,那么这个message就会和他的hander被MessageQueue一直持有,需要在相应的位置对handler进行removeMessageCallback等操作线程造成的内存泄露线程的生命周期和activity不一样,就会导致activity中新起的线程,持有activity的一个引用,结果run方法还没有结束的话,activity就不会释放,如果此时activity早就已经用不到了,久造成了内存泄露。不良的代码习惯比如bitmap没有及时的recycle,各种io流没有及时的close,adapter中没有使用convertView

  • 14-1 讲一讲你所知道的java的GC算法吧

引用计数:一个对象被引用计数器加一,取消引用计数器减一,引用计数器为0才能被回收。优点:简单。缺点:不能解决循环引用的问题,比如A引用B,B引用A,但是这两个对象没有被其他任何对象引用,属于垃圾对象,却不能回收;每次引用都会附件一个加减法,影响性能。标记清除法:分为两个阶段:标记阶段和清除阶段。标记阶段通过根节点标记所有可达对象,清除阶段清除所有不可达对象。缺点:因为清除不可达对象之后剩余的内存不连续,会产生大量内存碎片,不利于大对象的分配。复制算法:将内存空间分成相同的两块,每次只是用其中的一块,垃圾回收时,将正在使用的内存中的存活对象复制到另外一块空间,然后清除正在使用的内存空间中的所有对象,这种回收算法适用于新生代垃圾回收。优点:垃圾回收对象比较多时需要复制的对象恨少,性能较好;不会存在内存碎片。缺点:将系统内存折半。标记压缩算法:是一种老年代回收算法,在标记清除的基础上做了一些优化,首先从根节点开始标记所有不可达的对象,然后将所有可达的对象移动到内存的一端,最后清除所有不可达的对象。优点:不用将内存分为两块;不会产生内存碎片。分代算法:新生代使用复制算法,老生带使用标记清除算法或者标记压缩算法。几乎所有的垃圾回收期都区分新生代和老生带。分区算法:将整个堆空间分成很多个连续的不同的小空间,每个小空间独立使用,独立回收。为了更好的控制gc停顿时间,可以根据目标停顿时间合理地回收若干个小区间,而不是整个堆空间,从而减少gc停顿时间。

  • 14-2 你所知道的哪些东西需要及时的去关闭或者是释放的?

比如BroadCastReceiver,ContentReceiver,FileObserver,Callback什么的都需要在onDestory方法或者在activity的生命周期结束的时候回收,否则activity会被系统强引用,无法回收。比如bitmap没有及时的recycle,各种io流没有及时的close,adapter中没有使用convertView

fresco的优点:

* 支持流式,支持类似于网页上的从模糊到清晰加载图片,渐进式加载JPEG图片。
* 图片可以从任意的中心点显示在imageView,而不仅仅是图片的中心。
* 支持多帧动画,GIF,webP.
* 缺点: 框架较大,影响apk的体积,使用较繁琐。

1.为什么Fragment被称为第五大组件?

大屏幕 展现ui,ui切换效果,动态灵活的加入到activity

15.scrollView怎么去判断有没有滑到了底部?

首先我们判断肯定是要放在touch监听当中,比如scrollview的onTouchListener或者是他自己的onScrollChange中。在ontouch中,当检测到up动作的时候,判断getScrollY

  • getHeight = view.getChildAt.getMeasureHeight()的时候就是到了底部或者在onScrollChange方法中,通过View view = getchildAt(getChildCount获得最下面的一个view(其实就是scrollView包裹的唯一子view),然后获得它的高度,view.getBottom(),然后当这个高度等于scrollY getHeight的时候就是滑到了底部
  • 15-1 getScrollY()表示什么意思?

可以理解位控件上方滑出屏幕的距离,如果为负,就表示已经滑到了控件的顶端

网络请求框架Volley 和Ok-http,android-async-http,retrofit的区别:

  1. 参考博文:http://www.cnblogs.com/changyaohua/p/4992987.html

2.Fragment加载到Activity中的两种方式

静态加载:布局文件中通过fragment标签引入

动态加载
FragmentManager 管理
FragmentTransation 添加,替换

transaction=fm.benginTransaction();  
transaction.add();  //添加到上面去,会重叠显示  
transaction.replace();//替换 remove()和add的合体  
transactioin.hide();//隐藏起来,不会重新绘制 
transaction.remove();  //移除掉 
transaction.commit(); 

16. assets和raw有什么不同和相同?

两个文件夹的文件都不会跟着压制apk被编译压缩,都是原封不动的保存。raw文件下不可以再有目录,而assets文件下可以再有目录raw文件夹下面的文件会映射到R文件中,调用的时候直接去使用R.raw.xxxx就可以访问,getResources().openRawResource(R.raw.rawtext)而assets文件下的文件访问的时候需要用到AssetManager,AssetManager assets = getAssets(); assets.open;

  • 16-1 什么时候用assets,什么时候去用raw

有些文件不得不放在raw中,因为直接可以通过R文件去访问,可以直接在xml文件中去访问他,而assets中由于没有产生R文件的映射,访问的速度应该是没有Raw文件来的快的。

volley框架:

* google推出的异步网络请求框架和图片加载框架,适合数据量小,通信频繁的网络操作。
* 能够使网络通信更快,更简单,拓展性更好一点,
* get,post网络请求以及网络图像的高效率异步处理请求。
* 可以对网络请求进行排序优先级管理。
* 支持网络请求的缓存
* 多级别取消请求
* 使用volley可以简化一些网络通信的开发,不适合大数据和流媒体的网络请求,例如上百兆文件,视频上传。
* volley在Android2.2以下使用httpClient,2.2以上使用的是httpUriConnection.
* Volley的使用:http://blog.csdn.net/sinyu890807/article/details/17482095

基本的使用方法: http://www.kwstu.com/ArticleView/kwstu_20144118313429
直接返回Object的话,用Gson/FastJson与Volley的结合:http://www.cnblogs.com/freexiaoyu/p/3955137.html

* Volley问题收录:Volley的request默认回调到主线程中,如果有需求是要加载到sqlite等等仍需要在子线程中进行的操作 解决方案 :https://www.zhihu.com/question/36672622/answer/76003423   

3.Fragment回退栈

多个frament显示时,为了能点击back键时,能有像activity一样的效果,我们需要使用FragmentTransaction.addToBackStack()方法;

17. 数据持久化的四中方式?

preference,SQlite,文件I/O,ContentProvider

async-Http框架:

* 清晰地网络请求回调
* 网络请求使用线程池ThreadPool,限制并发资源使用情况
* get/post基于参数构建使用(RequestParams)
* 支持Multipart文件上传,大数据上传下载。
* 内置响应解析成json.
* 持久化cookie存储,保存cookie到应用程序的sharedPreferences.
* 支持二进制文件,图片的下载
* 使用的是httpClient

4.FragmentPagerAdapter与FragmentStatePagerAdapter区别

ViewPager与Fragment结合使用;

前者适用页面较少: detach 并没有回收内存,ui分离
后者使用页面较多: remove 回收内存

18. 显式和隐式的intent调用分别怎么调用?

显式:intent直接定义的时候传入指定的class,或者是component,或者是setClass/setClassName隐式:不明确指定具体的class,而是采用setAction的方式,来启动注册了添加了这个action的filter的activity。如果找到一个就打开一个,如果找到多个,系统会让你进行选择,,如果一个都没有找到,就跳出来activitynotfoundexception

okhttp框架:

* OKhttp和retrofit都出自于Square公司,是高性能的http库。
* OKhttp使用okio进行数据传输,  包含一般的get,post请求;基于http的文件,图片上传,加载;支持请求回调,直接返回对象,对象集合;支持session的保持。
* 支持spdy,http2.0,websocket,支持同步,异步,
* 封装了线程池,数据转换,参数使用,错误处理等;
* OKhttp使用教程:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0106/2275.html

3-4 Fragment面试二

19. 自定义viewgroup,实现过么?

继承自ViewGroup,主要的就是实现onMeasure方法和onLayout方法,因为onDraw方法只需要调用super.onDraw方法即可。在onMeasure,根据获得父框架给予的宽高大小和宽高模式,来计算子view排布之后的布局的宽高。如果在xml文件中直接定义了dp的具体数值,或者是直接是match_parent,则直接调用setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY)?sizeWidth: width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight: height); 根据尺寸模式来判断是要使用自己计算出来的宽高还是父框架给予的宽高在onLayout中,就对子view进行排布。定义left = 0,和top = 0,然后根据分布的规则,遍历自view,计算出他们的left,top,right,bottom的值,然后调用自view的layout方法,去排列它们

  • 19-1 具体需要实现哪些方法呢?

onMeasure, onLayout,依据情况还可以实现onDraw等方法

19-1-1 知道流布局么,让你实现怎么实现,大体讲一讲?

通过onMeasure对内部组件进行遍历计算宽度和高度,如果内部组件的宽度和比父类给予的宽度大了就开第二行进行计算,并叠加高度,.依次来进行计算控件的宽高,然后调用setMeasureDimension.通过onLayout来计算坐标点,计算方式跟onMeasure方式相同,只是宽高存储改为坐标存储.

retrofit框架:

* 出自于Square公司,是对OKhttp做了一层封装。
* 支持Gson解析,retrofit已经在内部封装了json解析

1. Fragment生命周期

不是独立的,需要结合Activity的生命周期;
以下是启动到销毁的全过程:
onAttach
onCreate
onCreateView
onViewCreated
Activity:onCreate
onActivityCrearted
Activity:onStart
onStart
Activity:onResume
onResume
初始化完成

onPause
Activity:onPause
onStop
Activity:onStop
onDestroyView
onDestroy
onDetach
Activity:onDestroy

本文由澳门皇冠金沙网站发布于编辑程序,转载请注明出处:Android面试基础题总结二,听课笔记