面试篇Android面试面试

Android 面试之 Android 篇一

2016-12-10  本文已影响534人  eddy_wiki

本文出自 Eddy Wiki ,转载请注明出处:http://eddy.wiki/interview-android.html

本文收集整理了 Android 面试中会遇到与 Android 知识相关的简述题。

基本概念

Android 的四大组件

Acitivity、Service、BroadcastReceiver、ContentProvider

Activity :

应用程序中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。

BroadcastReceiver广播接收器:

应用程序可以使用它对外部事件进行过滤只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice 来响应它们收到的信息,或者用NotificationManager 来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。

Service 服务:

一个Service 是一段长生命周期的,没有用户界面的程序,可以用来开发如监控类程序。

Content Provider内容提供者 :

android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。这些数据可以存储在文件系统中、在一个SQLite数据库、或以任何其他合理的方式。其他应用可以通过ContentResolver类(见ContentProviderAccessApp例子)从该内容提供者中获取或存入数据.(相当于在应用外包了一层壳),只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处:统一数据访问方式。

参考:

Android四大基本组件介绍与生命周期

四大组件的具体作用以及用法

Android平台的framework的层次结构?

应用层、应用框架层、中间件(核心库和运行时)、Linux内核

Activity

Activity 生命周期

Activity和Fragment生命周期有哪些?

Activity——onCreate->onStart->onResume->onPause->onStop->onDestroy

Fragment——onAttach->onCreate->onCreateView->onActivityCreated->onStart->onResume->onPause->onStop->onDestroyView->onDestroy->onDetach

Activity四种启动模式的区别(LanchMode 的应用场景)

这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。

如果在任务的栈顶正好存在该Activity的实例,就重用该实例( 会调用实例的 onNewIntent() ),否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。

如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的 onNewIntent() )。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

在一个新栈中创建该Activity的实例,并让多个应用共享该栈中的该Activity实例。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例( 会调用实例的 onNewIntent() )。其效果相当于多个应用共享一个应用,不管谁激活该 Activity 都会进入同一个应用中。

设置启动模式的位置在 AndroidManifest.xml 文件中 Activity 元素的 Android:launchMode 属性。

singleTop适合接收通知启动的内容显示页面。例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。

singleTask适合作为程序入口点。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。

singleInstance应用场景:闹铃的响铃界面。 你以前设置了一个闹铃:上午6点。在上午5点58分,你启动了闹铃设置界面,并按 Home 键回桌面;在上午5点59分时,你在微信和朋友聊天;在6点时,闹铃响了,并且弹出了一个对话框形式的 Activity(名为 AlarmAlertActivity) 提示你到6点了(这个 Activity 就是以 SingleInstance 加载模式打开的),你按返回键,回到的是微信的聊天界面,这是因为 AlarmAlertActivity 所在的 Task 的栈只有他一个元素, 因此退出之后这个 Task 的栈空了。如果是以 SingleTask 打开 AlarmAlertActivity,那么当闹铃响了的时候,按返回键应该进入闹铃设置界面。

Activity中类似onCreate、onStart运用了哪种设计模式,优点是什么

模板模式。每次新建一个Actiivty时都会覆盖onCreate,onStart等方法,这些方法在父类中就相当于一个模板。

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

android:theme="@android:style/Theme.Dialog"  

Activity的启动过程

  1. 无论是通过Launcher来启动Activity,还是通过Activity内部调用startActivity接口来启动新的Activity,都通过Binder进程间通信进入到ActivityManagerService进程中,并且调用ActivityManagerService.startActivity接口;
  2. ActivityManagerService调用ActivityStack.startActivityMayWait来做准备要启动的Activity的相关信息;
  3. ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread代表的是调用ActivityManagerService.startActivity接口的进程,对于通过点击应用程序图标的情景来说,这个进程就是Launcher了,而对于通过在Activity内部调用startActivity的情景来说,这个进程就是这个Activity所在的进程了;
  4. ApplicationThread不执行真正的启动操作,它通过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否需要创建新的进程来启动Activity;
  5. 对于通过点击应用程序图标来启动Activity的情景来说,ActivityManagerService在这一步中,会调用startProcessLocked来创建一个新的进程,而对于通过在Activity内部调用startActivity来启动新的Activity来说,这一步是不需要执行的,因为新的Activity就在原来的Activity所在的进程中进行启动;
  6. ActivityManagerService调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操作;
  7. ApplicationThread把这个启动Activity的操作转发给ActivityThread,ActivityThread通过ClassLoader导入相应的Activity类,然后把它启动起来。

window和activity之间关系?

WindowManager 的相关知识

Activity、Window 和 View 三者的区别

Activity 是控制单元,Window 是承载模型,View 是显示视图

一个activity打开另外一个activity,再打开一个activity?回去的时候发生了什么操作?

onActivityResult(int requestCode, int resultCode, Intent data)方法的用法;

如果你想在Activity中得到新打开Activity关闭后返回的数据,你需要使用系统提供的startActivityForResult(Intent intent,int requestCode)方法打开新的Activity,新的Activity关闭后会向前面的Activity传回数据,为了得到传回的数据,你必须在前面的Activity中重写onActivityResult(int requestCode, int resultCode,Intent data)方法。

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

A使用startActivityForResult方法开启B,B类结束时调用finish;A类的Intent有一个子Activity结束事件onActivityResult,在这个事件里继续播放音乐。

内存不足时,怎么保持Activity的一些状态,在哪个方法里面做具体操作?

在onSaveInstanceState方法中保存Activity的状态,在onRestoreInstanceState或onCreate方法中恢复Activity的状态

onSaveInstanceState方法

onRestoreInstanceState(Bundle savedInstanceState)方法

同一个程序不同的Activity如何放在不同的任务栈中?

需要为不同的activity设置不同的affinity属性,启动activity的Intent需要包含FLAG_ACTIVITY_NEW_TASK标记。

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

有几种在activity之间切换的方法?

startActivity()

startActivityForResult()

Fragment

Fragment生命周期

Activity中如何动态的添加Fragment?

//向活动添加碎片,根据屏幕的纵向和横向显示
//1,获取碎片管理器
FragmentManager fragment=getFragmentManager();
//2,碎片的显示需要使用FragmentTransaction类操作
FragmentTransaction transacction=fragment.beginTransaction();
//获取屏幕管理器和默认的显示
Display display=getWindowManager().getDefaultDisplay();
//判断横屏
if(display.getWidth()>display.getHeight()){
    //获取java类
    Frament1 frament1 =  new Frament1();
    transacction.replace(android.R.id.content, frament1);
}else{
    Frament2 frament2 =  new Frament2();
    transacction.replace(android.R.id.content, frament2);
}
//使用FragmentTransaction必须要commit
transacction.commit();

Fragment 特点

Fragment嵌套多个Fragment会出现bug吗?

参考:http://blog.csdn.net/megatronkings/article/details/51417510

怎么理解Activity和Fragment的关系?

Service

Service的生命周期。

Service是运行在后台的android组件,没有用户界面,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序的上下
文里。

Service随着启动形式的不同,其生命周期稍有差别。当用Context.startService()来启动时,Service的生命周期依次为:oncreate——>onStartCommand——>onDestroy

当用Context.bindService()启动时:onStart——>onBind——>onUnbind——>onDestroy

Service有哪些启动方法,有什么区别,怎样停用Service?

Service启动方式有两种;一是Context.startService和Context.bindService。

区别是通过startService启动时Service组件和应用程序没多大的联系;当用访问者启动之后,如果访问者不主动关闭,Service就不会关闭,Service组件之间因为没什么关联,所以Service也不能和应用程序进行数据交互。

而通过bindService进行绑定时,应用程序可以通过ServiceConnection进行数据交互。在实现Service时重写的onBind方法中,其返回的对象会传给ServiceConnection对象的onServiceConnected(ComponentName name, IBinder service)中的service参数;也就是说获取了serivce这个参数就得到了Serivce组件返回的值。Context.bindService(Intent intent,ServiceConnection conn,int flag)其中只要与Service连接成功conn就会调用其onServiceConnected方法

停用Service使用Context.stopService

注册Service需要注意什么

无论使用哪种启动方法,都需要在xml里注册你的Service,就像这样:

<service
  android:name=".packnameName.youServiceName"
  android:enabled="true" />

service 可以执行耗时操作吗

不能,超过20s就会出现ARN

Service和Activity在同一个线程吗

默认情况下是在同一个主线程中。但可以通过配置android:process=":remote" 属性让 Service 运行在不同的进程。

Service分为本地服务(LocalService)和远程服务(RemoteService):

1、本地服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,

也不需要AIDL。相应bindService会方便很多。主进程被Kill后,服务便会终止。

2、远程服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,

不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。

按使用方式可以分为以下三种:

  1. startService 启动的服务:主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService;
  2. bindService 启动的服务:该方法启动的服务可以进行通信。停止服务使用unbindService
  3. startService 同时也 bindService 启动的服务:停止服务应同时使用stepService与unbindService

参考:http://www.cnblogs.com/linlf03/p/3296323.html

Service与Activity怎么实现通信

Service里面可以弹出 dialog 或 Toast 吗

可以。getApplicationContext()

Toast必须在UI主线程上才能正常显示,而在Service中是无法获得Acivity的Context的,在service中想显示出Toast只需将show的消息发送给主线程Looper就可以了。此时便可显示Toast。

Handler handler = new Handler(Looper.getMainLooper());  
handler.post(new Runnable() {  
  public void run() {  
    Toast.makeText(getApplicationContext(), "存Service is runing!",  
                   Toast.LENGTH_SHORT).show();  
  }  
}); 

Dialog的用法与此类似,但是要多加个权限,在manifest中添加此权限以弹出dialog

<uses-permission Android:name="android.permission.SYSTEM_ALERT_WINDOW" />
dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));  

什么时候使用Service?

比如播放多媒体的时候,用户启动了其他的Activity这个时候程序要在后台继续播放。比如检测SD卡上文件的变化。在或者在后台记录你地理位置的改变等等。

说说Activity、Intent、Service是什么关系

一个Activity通常是一个单独的屏幕,每一个Activity都被实现为一个单独的类,这些类都是从Activity基类中继承来的,Activity类显示有视图控件组成的用户接口,并对视图控件的事件做出响应。

Intent的调用是用来进行架构屏幕之间的切换的。Intent是描述应用想要做什么。Intent数据结果中最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。

Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序的上下文里。需要通过某一个Activity或其他Context对象来调用。

Activity 跳转到Activity,Activtiy启动Service,Service打开Activity都需要Intent表明跳转的意图,以及传递参数,Intent是这些组件间信号传递的传承者。

怎么在启动一个activity时就启动一个service

在activity的onCreate里写startService(xxx);然后this.finish();结束自己..

这是最简单的方法 可能会有屏幕一闪的现象,如果UI要求严格的话用AIDL把

为什么在Service中创建子线程而不是Activity中

这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。

Service 与 Thread 的区别

很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下。

1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。

2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!

既然这样,那么我们为什么要用 Service 呢?其实这跟 android 的系统机制有关,我们先拿 Thread 来说。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。

举个例子:如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。

因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。

如何保证 Service 在后台不被 kill

START_STICKY 在运行onStartCommand后service进程被kill后,那将保留在开始状态,但是不保留那些传入的intent。不久后service就会再次尝试重新创建,因为保留在开始状态,在创建 service后将保证调用onstartCommand。如果没有传递任何开始命令给service,那将获取到null的intent。

START_NOT_STICKY 在运行onStartCommand后service进程被kill后,并且没有新的intent传递给它。Service将移出开始状态,并且直到新的明显的方法(startService)调用才重新创建。因为如果没有传递任何未决定的intent那么service是不会启动,也就是期间onstartCommand不会接收到任何null的intent。

START_REDELIVER_INTENT 在运行onStartCommand后service进程被kill后,系统将会再次启动service,并传入最后一个intent给onstartCommand。直到调用stopSelf(int)才停止传递intent。如果在被kill后还有未处理好的intent,那被kill后服务还是会自动启动。因此onstartCommand不会接收到任何null的intent。

在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。

Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:

1.前台进程( FOREGROUND_APP)
2.可视进程(VISIBLE_APP )
3.次要服务进程(SECONDARY_SERVER )
4.后台进程 (HIDDEN_APP)
5.内容供应节点(CONTENT_PROVIDER)
6.空进程(EMPTY_APP)

当service运行在低内存的环境时,将会kill掉一些存在的进程。因此进程的优先级将会很重要,可以使用startForeground 将service放到前台状态。这样在低内存时被kill的几率会低一些。

service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;

通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活,别忘记加权限啊。

什么是IntentService?有何优点?

IntentService也是一个Service,是Service的子类;IntentService和Service有所不同,通过Looper和Thread来解决标准Service中处理逻辑的阻塞的问题。

优点:Activity的进程,当处理Intent的时候,会产生一个对应的Service,Android的进程处理器现在会尽可能的不kill掉你。

IntentService的使用场景与特点。

IntentService是Service的子类,是一个异步的,会自动停止的服务,很好解决了传统的Service中处理完耗时操作忘记停止并销毁Service的问题

优点:

onStartCommand中回调了onStart,onStart中通过mServiceHandler发送消息到该handler的handleMessage中去。最后handleMessage中回调onHandleIntent(intent)。

IntentService 作用是什么

IntentService 是继承于 Service 并处理异步请求的一个类,在IntentService 内有一个工作线程来处理耗时操作,启动 IntentService 的方式和启动传统 Service 一样,同时,当任务执行完后,IntentService 会自动停止,而不需要我们去手动控制。另外,可以启动 IntentService 多次,而每一个耗时操作会以工作队列的方式在 IntentService 的 onHandleIntent 回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

IntentService 与 Service的异同

ContentProvider

参考:http://blog.csdn.net/coder_pig/article/details/47858489

ContentProvider 简介

ContentProvider(内容提供者):为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider

  1. ContentProvider 为存储和读取数据提供了统一的接口
  2. 使用ContentProvider,应用程序可以实现 app 间数据共享
  3. Android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

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

创建一个属于你自己的Content provider或者将你的数据添加到一个已经存在的Content provider中,前提是有相同数据类型并且有写入Content provider的权限。

ContentProvider使用方法

参考:http://blog.csdn.net/juetion/article/details/17481039

Broadcast

注册广播有哪几种方式,有什么区别

registerReceiver(receiver,filter);// 注册BroadcastReceiver
unregisterReceiver(receiver);// 取消注册BroadcastReceiver

当BroadcastReceiver更新UI,通常会使用这样的方法注册。启动Activity时候注册BroadcastReceiver,Activity不可见时候,取消注册。

<receiver>
    <intent-filter>
     <action Android:name = "android.intent.action.PICK"/>
    </intent-filter>
</receiver>

1)第一种不是常驻型广播,也就是说广播跟随程序的生命周期。

2)第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。

一个 app 被杀掉进程后,是否还能收到广播

静态注册的常驻型广播接收器还能接收广播。

Android引入广播机制的用意?

无序广播、有序广播

本地广播和全局广播有什么差别

全局广播 BroadcastReceiver 是针对应用间、应用与系统间、应用内部进行通信的一种方式。

本地广播 LocalBroadcastReceiver 仅在自己的应用内发送接收广播,也就是只有自己的应用能收到。因广播数据在本应用范围内传播,不用担心隐私数据泄露的问题。 不用担心别的应用伪造广播,造成安全隐患。 相比在系统内发送全局广播,它更高效。

Intent

Intent的使用方法,可以传递哪些数据类型。

通过查询Intent/Bundle的API文档,我们可以获知,Intent/Bundle支持传递基本类型的数据和基本类型的数组数据,以及String/CharSequence类型的数据和String/CharSequence类型的数组数据。而对于其它类型的数据貌似无能为力,其实不然,我们可以在Intent/Bundle的API中看到Intent/Bundle还可以传递Parcelable(包裹化,邮包)和Serializable(序列化)类型的数据,以及它们的数组/列表数据。

所以要让非基本类型和非String/CharSequence类型的数据通过Intent/Bundle来进行传输,我们就需要在数据类型中实现Parcelable接口或是Serializable接口。

参考:http://blog.csdn.net/kkk0526/article/details/7214247

介绍一下Intent、IntentFilter

Context

Context区别

Application Context 和 Activity Context 异同

Context 的理解

Handler

Handler 原理

Andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。

Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的MessageQueue(消息队列)。

Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。

Message Queue(消息队列):用来存放线程放入的消息。

线程:UIthread 通常就是main thread,而Android启动程序时会替它建立一个MessageQueue。

参考:

Handler、Looper、Message、MessageQueue基础流程分析

Handler消息机制,postDelayed会造成线程阻塞吗?对内存有什么影响?

Handler, Looper的理解

Handler,Message,Looper异步实现机制与源码分析

参考:

Android 消息处理机制(Looper、Handler、MessageQueue,Message)

Handler有何作用?如何使用之(具体讲需要实现什么function)?

Android设计了Handler机制,由Handler来负责与子线程进行通讯,从而让子线程与主线程之间建立起协作的桥梁,使Android的UI更新的问题得到完美的解决。

参考:

Handler有何作用?如何使用?

Handler、Thread 和 HandlerThread 的区别

Handler 会关联一个单独的线程和消息队列。Handler默认关联主线程(即 UI 线程),虽然要提供Runnable参数 ,但默认是直接调用Runnable中的run()方法。也就是默认下会在主线程执行,如果在这里面的操作会有阻塞,界面也会卡住。如果要在其他线程执行,可以使用 HandlerThread。

HandlerThread继承于Thread,所以它本质就是个Thread。与普通Thread的差别就在于,主要的作用是建立了一个线程,并且创立了消息队列,有自己的looper,可以让我们在自己的线程中分发和处理消息。

android.os.Handler可以通过Looper对象实例化,并运行于另外的线程中,Android提供了让Handler运行于其它线程的线程实现,也是就HandlerThread。HandlerThread对象start后可以获得其Looper对象,并且使用这个Looper对象实例Handler。

参考:

Android中的Thread & HandlerThread & Handler

使用 Handler 时怎么避免引起内存泄漏

一旦Handler被声明为内部类,那么可能导致它的外部类不能够被垃圾回收。如果Handler是在其他线程(我们通常成为worker thread)使用Looper或MessageQueue(消息队列),而不是main线程(UI线程),那么就没有这个问题。如果Handler使用Looper或MessageQueue在主线程(main thread),你需要对Handler的声明做如下修改:

  1. 声明Handler为static类;
  2. 在外部类中实例化一个外部类的WeakReference(弱引用)并且在Handler初始化时传入这个对象给你的Handler;
  3. 将所有引用的外部类成员使用WeakReference对象。
private static class MyHandler extends Handler {          
  private final WeakReference<HandlerActivity2> mActivity; 
  
  public MyHandler(HandlerActivity2 activity) {              
    mActivity = new WeakReference<HandlerActivity2>(activity);          
  }
  
  @Override          
  public void handleMessage(Message msg) {              
    System.out.println(msg);             
    if (mActivity.get() == null) {                  
        return;              
    }              
    mActivity.get().todo();          
  }      
}  

当Activity finish后 handler对象还是在Message中排队。 还是会处理消息,这些处理有必要?正常Activitiy finish后,已经没有必要对消息处理,那需要怎么做呢?解决方案也很简单,在Activity onStop或者onDestroy的时候,取消掉该Handler对象的Message和Runnable。通过查看Handler的API,它有几个方法:removeCallbacks(Runnable r)和removeMessages(int what)等。

/**    * 一切都是为了不要让mHandler拖泥带水    */   
@Override   
public void onDestroy() {       
  mHandler.removeMessages(MESSAGE_1);       
  mHandler.removeMessages(MESSAGE_2);       
  mHandler.removeMessages(MESSAGE_3);        
  // ... ...         
  mHandler.removeCallbacks(mRunnable);         
  // ... ...   
}  

参考:

Handler内存泄漏分析及解决

AsyncTask

AsyncTask原理

参考:

深入理解AsyncTask的工作原理

网络请求是怎么做的异步呢?什么情况下用Handler,什么情况下用AsyncTask

Handler和AsyncTask的区别

这俩类都是用来实现异步的,其中AsyncTask的集成度较高,使用简单,Handler则需要手动写Runnable或者Thread的代码;另外,由于AsyncTask内部实现了一个非常简单的线程池,实际上是只适用于轻量级的异步操作的,一般不应该用于网络操作。(感谢网友指正,AsyncTask 通过重写的方式是可以用于长耗时操作的,而我只考虑了直接使用的情况就说它不适合网络操作,是不对的。)我问他Handler和AsyncTask的区别,一方面是因为他说用AsyncTask联网,因此我认为他对AsyncTask并不熟悉;但更重要的是在我问他实现异步的具体手段的时候,他同时提到了Handler和AsyncTask——用这种“混搭”的使用方式来写联网框架,就算不考虑AsyncTask的可用性,也显得非常怪异,这听起来更像是在“列举Android实现异步操作最常用的类”,而非“讲述实现网络异步操作的具体方式”。也就是说,我听了这句话后开始怀疑他封装过联网框架这件事的真实性。但我只是怀疑,并不确定,因此接着问了我想问的。

参考:

https://www.zhihu.com/question/30804052

AsyncTask的优缺点?能否同时并发100+AsyncTask呢?

参考:

AsyncTask到底是什么

上一篇 下一篇

猜你喜欢

热点阅读