android面试,那些年我们遗忘的基础

1.什么是Activity?问的不太多,说点有深度的

四大组件之一,一般的,一个用户交互界面对应一个activity

setContentView() ,// 要显示的布局

, activity 是Context的子类,同时实现了window.callback和keyevent.callback, 可以处理与窗体用户交互的事件.

button.setOnclickLinstener{

}

我开发常用的的有ListActivity, PreferenceActivity ,TabAcitivty等…

PreferenceActivity与设置有关的activity

TabActivity就是有一个Tabhost

如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity.

界面的初始化,进度对话框的显示与销毁doubanservice

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

生命周期描述的是一个类 从创建(new出来)到死亡(垃圾回收)的过程中会执行的方法..

在这个过程中 会针对不同的生命阶段会调用不同的方法

Activity从创建到销毁有多种状态,从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:oncreate ondestroy onstop onstart onresume onpause

其实这些方法都是两两对应的:

onCreate创建与onDestroy销毁;

onStart可见与onStop不可见;

onResume可编辑(即焦点)与onPause;

对话框是activity的一部分.

所以对话框的弹出,指定上下文必须是 Activity.this

所以弹出对话框(对话框获取焦点)不会调用任何生命周期方法

这6个方法是相对应的,那么就只剩下一个onRestart方法了,这个方法在什么时候调用呢?

答案就是:在Activity被onStop后,但是没有被onDestroy,在再次启动此Activity时就调用onRestart(而不再调用onCreate)方法;

如果被onDestroy了,则是调用onCreate方法。

最后讲自己项目中的经验,比如说豆瓣客户端每次进入某个界面的时候都要看到最新的数据,这个刷新列表的操作 就放在onStart()的方法里面.

fillData() 这样保证每次用户看到的数据都是最新的.

多媒体播放, 播放来电话.

onStop() 视频声音设置为0 , 记录视频播放的位置 mediaplayer.pause();

onStart() 根据保存的状态恢复现场. mediaplayer.start();

在读文档的时候 还发现 activity还有两个方法 onPostResume() 和 OnPostCreate()这两个生命周期的方法,不过开发的时候没有用到过.

这俩方法一般开发是用不到,是给框架使用的,在onResume和onCreate方法之前调用

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

一般情况比如说有两个activity,分别叫A,B ,当在A里面激活B组件的时候, A 会调用 onPause()方法,然后B 调用onCreate() ,onStart(), OnResume() ,

这个时候B覆盖了窗体, A会调用onStop()方法.如果B呢 是个透明的,或者是对话框的样式,就不会调用onStop()方法

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

这个生命周期跟清单文件里的配置有关系

1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期

默认首先销毁当前activity,然后重新加载

onpause onstop ondestory oncreate onstart onresume

2、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

Api13以上还需要给configChanges配置screensize一个值

游戏开发中, 屏幕的朝向都是写死的. 因为如果可以切换横竖屏,那么用户体验不好,而且还要保持游戏相关数据,比较消耗时间性能。

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

可以自定义一个activity的样式,style中增加theme:

新建一个Theme,指定他的parent为android:Theme.Dialog,然后Activity添加这个theme即可。

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

除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.

当activity被系统异常回收时调用onSaveInstanceState方法

protectedvoidonSaveInstanceState(Bundle outState) {

super.onSaveInstanceState(outState);

outState.putLong("id", 1234567890);

}

publicvoidonCreate(Bundle savedInstanceState) {

//判断 savedInstanceState是不是空.

//如果不为空就取出来

super.onCreate(savedInstanceState);

}

7.如何退出Activity?如何安全退出已调用多个ActivityApplication

应用场景,例如UC浏览器,你打开了100个页面,然后通常做法是点击返回,点击100次才能正常退出Application。这样用户体验太差,UC浏览器的菜单提供了退出按钮,点击退出即可安全退出应用。

退出activity 直接调用 finish () 方法 . //用户点击back键 就是退出一个activity

退出activity 会执行 onDestroy()方法 .

做法:

1、抛异常强制退出:测试没通过?

该方法通过抛异常,使程序Force Close。 Force close,系统会清空我们的任务栈,清空所有打开的界面。

验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。

//安全结束进程android.os.Process.killProcess(android.os.Process.myPid());

2、记录打开的Activity:

思路:

每打开一个Activity,通过就记录下来。手动退出时,就移除集合。点击退出按钮时,循环关闭集合中的Activity。

步骤:

定义MyApp 继承Application,然后再清单文件中给Application节点指定name为MyApp。

定义成员变量List lists ;

在生命周期方法onCreate方法中初始化:lists = new ArrayList();

每一个activity在执行onCreate()方法的时候 lists.add(this);

Ondestory() lists.remove(this);

当点击退出按钮时,循环关闭集合中的activity

for(Activity activity: lists)

{

activity.finish();

}

3、发送特定广播:

在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。

//给某个activity 注册接受接受广播的意图

registerReceiver(receiver, filter)

//如果过接受到的是 关闭activity的广播就调用finish()方法 把当前的activity finish()掉

4、递归退出(不推荐)

在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。

404 退出程序

OnActivityResult();

*讲一讲你对activity的理解 (有些公司会出一些这种题目,对xxx的理解)

把自己的心得写出来即可。

Activity用于与用户交互。

在讲一讲Activity的生命周期,可以利用这些生命周期方法做初始化,

例如:进入某个界面的时候都要看到最新的数据,就要在onstart方法内填充数据。

还有处理横竖屏时,Activity会摧毁重构,我们在特殊场景需要做特殊处理,

例如:播放器,正播放时,打入电话,我们需要在onstop方法保存播放进度,然后再onstart方法内读取进度,继续播放。

游戏,固定横竖屏。

简单介绍onPostResume() 和 OnPostCreate

Activity被系统回收时,需要做的一些操作:重写onSaveInstanceState

打开多个Activity,如何安全退出Application

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

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

service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )

在子线程中执行 new Thread(){}.start();

特殊情况,可以在清单文件配置 service 执行所在的进程 ,

让service在另外的进程中执行

"cn.itcast.xxx">

9.两个Activity之间怎么传递数据?

通过Intent传递数据:

基本数据类型可以通过Intent 传递数据

extras.putDouble(key,value)

intent.putExtra(name, value)

传递Bundle对象

Bundle bundle = newBundle();

bundle.putShort(key, value);

intent.putExtras(bundle);

获取数据

获取到激活他的Intent:

Intent intent = getIntent();

Bundlebundle= intent.getExtras();

Bundle类似map的集合 ,存放键值对

intent.getStringExtra("key","value");

intent.getBooleanExtra("key","value")

通过Application传递数据

自己去实现自己的application的这个类,基础系统的application ,每个activity都可以取到

利用这点,我们可以在Application 定义全局变量 ,然后通过这个变量来存储数据。

让对象实现 implementsSerializable接口把对象存放到文件上.

让类实现Serializable接口,然后可以通过ObjectOutputStream//对象输出流

File file =newFile("c:\\1.obj");

FileOutputStream fos=newFileOutputStream(file);

ObjectOutputStream oos =newObjectOutputStream(fos);

Student stu =newStudent();

stu.setId("10001");

stu.setName("zs");

oos.writeObject(stu);

FileInputStream fis =newFileInputStream(file);

ObjectInputStream ois =newObjectInputStream(fis);

Student stu1 = (Student) ois.readObject();

System.out.println(stu1.getName());

Parcelable和Serializable

谷歌工程师认为,将文件通过Serializable序列化到文件,然后再读取文件内容加载到内存,太浪费资源,就重写了Serializable,搞了一个Parcelable

Parcelable把对象序列化到android操作系统的一块公用的内存空间,直接操作内存,所以效率会比较高。

Intent传递数据的引用 (大资源文件,都是通过uri方式传递)

intent.setData(Uri)

Uri.fromFile();//大图片的传递

contentResolver.getInputStream(uri);//获取uri对应的流

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

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

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

比方说在激活一个新的activity时候, 给intent设置flag

Intent的flag添加FLAG_ACTIVITY_NEW_TASK单独的任务栈

这个被激活的activity就会在新的task栈里面…

也可以通过配置文件:android:launchMode="singleInstance"

Intent intent = new Intent(A.this,B.class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

service、broadCastReceiver开启Activity,因为他们默认没有任务栈,所以需要设置flag。设置这个Flag之后,在开启Activity时,会判断当前有木有存在任务栈,如果有则直接用,没有则创建。

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

startService() 一旦被创建就与调用着无关 ,没法使用service里面的方法

bindService () 把service 与调用者绑定 ,如果调用者被销毁, service会销毁

bindService() 我们可以使用service 里面的方法

bindService().让activity能够访问到 service里面的方法

绑定service的步骤:

构建一个intent对象,

Intent service = new Intent(this,MyService.class);

通过bindService的方法去启动一个服务,

bindService(intent, new MyConn(), BIND_AUTO_CREATE);

(MyConn)ServiceConnection 对象(重写onServiceConnected和OnServiceDisconnected方法)

BIND_AUTO_CREATE.:如果这个服务没有开启过,则自动开启

代码:

private class myconn implements ServiceConnection

{

//这个方法是异步操作,可能花费几秒的时间,所以执行完bindService是需要花费一定时间才能获取服务。

public void onServiceConnected(ComponentName name, IBinder service) {

// TODO Auto-generated method stub

//可以通过IBinder的对象 去使用service里面的方法

}

public void onServiceDisconnected(ComponentName name) {

// TODO Auto-generated method stub

}

}

13. 14 .什么是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的方法,那么就需要既开启服务,又绑定服务。

那么有一个原则是Service的onCreate的方法只会被调用一次,就是你无论多少次的startService又bindService,Service只被创建一次。

如果先是bind了,那么start的时候就直接运行Service的onStart方法,如果先是start,那么bind的时候就直接运行onBind方法。

如果service运行期间调用了bindService,这时候再调用stopService的话,service是不会调用onDestroy方法的,service就stop不掉了,只能调用UnbindService, service就会被销毁

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

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

多次调用unbindService的话会抛出异常。

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

这个问题问的很山寨.默认不做任何处理,B里面的音乐都能播放.

遇到问题, 可以随机应变,灵活发挥,多考虑些细节,比如说这个题就可以这样说,说说你对startActivityForResult的理解()

A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐.

不能通过onSaveInstanceStates来实现,因为他是activity被移除任务栈才执行的。

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

IntentService继承Service

普通的service ,默认运行在ui main 主线程

Sdk给我们提供的方便的,带有异步处理的service类,

异步处理的方法OnHandleIntent(),默认运行在子线程中,可以处理耗时的操作

17.什么时候使用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可以使用setForeground(true)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。

如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。

1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作. 天气预报 widget TimerTask Timer 定期执行timertask

2.Broadcast receiver捕获到一个事件之后,可以启动一个service来完成一个耗时的操作.

Broadcast receiver生命周期 和 响应时间很短(10s)

3.远程的service如果被启动起来,可以被多次bind, 但不会重新create.索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.

18.请描述一下IntentIntent Filter

Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。

通过Intent 可以实现各种系统组件的调用与激活.

Intent filter:可以理解为邮局或者是一个信笺的分拣系统,定义一些匹配条件

这个分拣系统通过3个参数来识别

Action: 动作Intent.ation_view

Data: 数据uriurimime

Category : 而外的附加信息

Action 匹配

Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的 Activity 定义时可以在其 节点指定一个 Action 列表用于标示 Activity 所能接受的“动作”,例如:

……

如果我们在启动一个 Activity 时使用这样的 Intent 对象:

Intent intent =new Intent();

intent.setAction("cn.itcast.action");

那么所有的 Action 列表中包含了“cn.itcast”的 Activity 都将会匹配成功。

Android 预定义了一系列的 Action 分别表示特定的系统动作。这些 Action 通过常量的方式定义在 android.content.Intent中,以“ACTION_”开头。我们可以在 Android 提供的文档中找到它们的详细说明。

URI数据匹配

一个 Intent 可以通过 URI 携带外部数据给目标组件。在 节点中,通过 节点匹配外部数据。

mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定数据的位置、端口、和路径。如下:

android:host="host" android:port="port" android:path="path"/>

电话的uritel: 12345

http://www.baidu.com

自己定义的uriitcast://cn.itcast/person/10

如果在 Intent Filter 中指定了这些属性,那么只有所有的属性都匹配成功时 URI 数据匹配才会成功。

Category类别匹配

节点中可以为组件定义一个 Category 类别列表,当 Intent 中包含这个列表的所有项目时 Category 类别匹配才会成功。

默认是DEFAULT

19. Intent传递数据时,可以传递哪些类型数据?

1.一般的基本数据类型Intent .putextra()intent.getStringextra();

2. 数据的uri, intent.setData()intent.getData();

20.说说ActivityIntentService是什么关系 。笔试常问

这种问题没什么水准,相当于麦当劳和麦当娜的关系是什么关系?

他们默认情况下是没有什么关系的。

这种问题,就讲下对activity, service,intent的理解。

再说一下 activity、service可以通过intent去激活组件,传递数据.

说自己项目中有这样一个网络更新的功能,显示界面就用的activity, 后台有个service每隔半小时都去访问下服务器获取更新的数据…

开启服务用的是intent来开启

注意所有的笔试,都要尽量说一下自己的项目的一些内容。

21.请描述一下Broadcast Receiver

广播是Android系统的一个事件,如果

有很多广播接收者 ,系统已经实现了.

广播分两种

有序广播:同步,优先级高的广播,会先接收到广播。

无序广播:异步

优先级使用:如果优先级一样,app的uid越低越先接收到广播(先安装的应用程序的uid会低一点。)

onReceive() 方法.

abortBroadcast();

有序广播有一个特例:指定接收者的广播 .是不可以被拦截掉的

sendOrderedBroadcast(intent,receiverPermission,resultReceiver,scheduler,initialCode,initialData,initialExtras);

resultReceiver广播接受者 如果我们显示的指定了广播接收者

无论如何 都会接受广播 事件abortBroadcast(); 的方法不会终止广播事件

除非:SetResultData(null);将数据置为null,接收者一看数据是null,就不会执行方法。

Sticky:粘性开发很少用到,但是面试有可能会问到:

sendStickyBroadcast(intent)//阴魂不散的广播 (粘性的广播)

粘性广播,会一直等待intent指定的事件处理完毕,才会消失。

Wifi设置:发送wifi状态改变的广播,系统就是通过sendStickyBroadcast来实现的,因为获取wifi状态改变是一个很耗时的操作,如果用一般发送广播方式,还没等wifi状态获取完,广播就结束了。用于接收系统的广播通知, 系统会有很多sd卡挂载,手机重启,广播通知,低电量,来短信等,一个apk的安装成功…

手机卫士中自定义一个broadcast receiver

sms_received

来获取短信到来的广播, 根据黑名单来判断是否拦截该短信.

画画板生成图片后,发送一个sd挂载的通知,通知系统的gallery去获取到新的图片.

Intent intent =newIntent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+Environment.getExternalStorageDirectory()));

sendBroadcast(intent);

广播接收者注册:

清单文件注册:一旦APK装到手机上,这个广播接收者就生效

代码注册:只有当代码执行时,才会生效

22.manifest和代码中如何注册和使 用broadcast receiver

设置广播接收者的优先级,设置广播接受者的action名字 等…

详细见工程代码.

代码中注册,如果代码没有执行,就接受不到广播事件

registerReceiver(receiver,filter);

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

ContentProvider是系统的一个服务,我们要实现数据共享需要重写ContentProvider

把自己的数据通过uri的形式共享出去

android系统下 不同程序 数据默认是不能共享访问

需要去实现一个类去继承ContentProvider

public class PersonContentProvider extends ContentProvider{

public boolean onCreate(){

//..

}

query(Uri, String[], String, String[], String)

insert(Uri, ContentValues)

update(Uri, ContentValues, String, String[])

delete(Uri, String, String[])

}

content:// 代表contentprovider

使用系统Provider

技巧: 1.看urlmarcher.

2. 根据匹配码 查看增删改查的具体实现

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

文件可以存到手机的内存,和sdcard中

手机内存文件存放位置: /data/data/包名/files

可以通过context.openFileInput(name)默认是私有的访问权限 ,只能读

Sdcard,读不需要权限,写需要权限。

数据库 sqlite:data/data/包名/database/xxx.db

SharedPreference//包名/shared_prepsContext.modeprivate

网络存放

socket 方式

httpHttpUrlConnection方式

HttpClient方式HttpPost HttpGet

ftp的网络file transport protocol

25.为什么要用ContentProvider?它和sql的实现上有什么差别?

可以根据自己的业务逻辑暴露相应操作,屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri和对应的参数,就可以了。

不同app之间共享,操作数据

但是contentprovider 还可以去增删改查本地文件. xml文件的读取,更改,

网络数据读取更改 (这种操作不多)

Sql也有增删改查的方法.

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

FrameLayout(帧布局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)

FrameLayout

从屏幕的左上角开始布局,叠加显示,

实际应用 播放器的暂停按钮.

获取数据时设置进度条的对话框

LinearLayout

线性布局,这个东西,从外框上可以理解为一个div,他首先是一个一个从上往下罗列在屏幕上。每一个LinearLayout里面又可分为垂直布局

(android:orientation="vertical")和水平布局(android:orientation="horizontal"

)。当垂直布局时,每一行就只有一个元素,多个元素依次垂直往下;水平布局时,只有一行,每一个元素依次向右排列。

AbsoluteLayout

绝对布局犹如div指定了absolute属性,用X,Y坐标来指定元素的位置android:layout_x="20px"

android:layout_y="12px"

qq斗地主 qq游戏大厅 800*480 800*480.apkfwvga854*480320*240

许多游戏还在使用绝对布局,因为绝对布局可以精准的知道组件的位置,可以做相应的点击事件。

RelativeLayout

相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有:

相对于某一个元素

android:layout_below="@id/aaa" 该元素在 id为aaa的下面

android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb

相对于父元素的地方

android:layout_alignParentLeft="true"在父元素左对齐

android:layout_alignParentRight="true" 在父元素右对齐

TableLayout

表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式 android:gravity="" 。

每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。

oa自动化 生成报表 ,图标 表示

css div

webview

有关布局的问题:平板的开发与手机的开发有什么样的区别:

区别主要区别在UI上。

平板任务管理器的界面布局用 gridview

手机 任务管理 listview

27.谈谈UI中,PaddingMargin有什么区别?

Padding 文字对边框, margin是控件与控件之间的距离

28. widget相对位置的完成在activity的哪个生命周期阶段实现。

这个题没看懂…

widget可以理解成桌面小控件,

onReceive方法,广播接收者?

也可以理解成 某个button, imageview这样的控件…

onMeasure() // 计算 控件在屏幕上的位子

onDraw 显示到界面上的

29.请解释下在单线程模型中MessageHandlerMessage QueueLooper之间的关系。

Activity的主线程被创建时,系统默认会帮创建Looper,然后会自动调用looper的parepare方法,让轮询器待命。

主线程中还有一个Message Queue的arrayList集合

因为只有主线程才可以更新UI,所以子线程A、子线程B要想更新UI,必须通过Handler去发送消息。发送的消息被放到Message Queue队列中,然后这个Looper轮询器,会不停的轮询Message Queue队列中的消息,如果发现有需要处理的消息,就会调用Message的handleMessage方法。

如何在子线程里面 显示土司?

手工调用:Looper.parepare();

显示Toast

手工轮询一次,发送消息:Looper.loop();

子线程中如果使用Looper,就不能再使用handler去发送消息,因为Looper会将消息发送给主线程。

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

Android interface definition language (android接口定义语言) ,

用来跨进程的访问方法,

访问远程的服务的方法. 如何工作 手机卫士程序锁

.endcall();

手机卫士 Itelephony 接口挂断电话.

31.请解释下Android程序运行时权限与文件系统权限的区别。

Android程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 打电话,访问网络,获取坐标,写sd卡,读写联系人等..安装的时候会提示用户…

文件系统的权限是linux系统的文件权限.

-rw------ 私有权限

-rw-rw-rw- 全局可读可写

比如说sharedpreference里面的Context.Mode_private

Context.Mode.world_read_ableContext.Mode_world_writeable

777最大权限,全局可读可写可执行

32.系统上安装了多种浏览器,能否指定某浏览器访问指定页面?

需要找到对应的浏览器的意图,传递数据URI , 激活这个意图

Intent .setAction(VIEW)

setData("http://")

激活系统的浏览器:

Intent intent =newIntent();

// com.android.browser/.BrowserActivity

intent.setClassName("com.android.browser","com.android.browser.BrowserActivity");

Intent.setdata(uri);

推广自己产品的操作,先查找手机里是否符合这个action的activity,如果没有就提示用户是否下载自己的产品:

queryIntentActivity();

33.android主线程的运用和理解

四大组件都是维护在主线程里

系统事件:低电量广播,sd卡挂载广播也是主线程来维护的。

主ui线程不能执行耗时的操作,不然会报anr异常

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

Android虚拟机很小,空间很小,谈谈移动设备的虚拟机的大小限制 默认 16M

由于每个应用所能使用的默认内存大小是16M,所有可以谈谈加载图片的时候怎么处理大图片的?

使用BitMap来对图片进行缩放。如何做***

垃圾回收,没有引用的对象(对象=null),或者是离开作用空间(局部变量),在某个时刻会被系统gc掉.

System.gc(); 显示通知系统是回收垃圾,不是立刻去执行垃圾回收.

手机电视项目

获取300个频道图片( 30K)将图片给gallery ,由于图片过多,有的频道界面图片是白板.

需要在gallery 显示图标的activity的ondestory中调用gc();回收图片资源

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

反射 , 配置文件 (所有框架都是这俩结合,框架工作原理,读取配置文件,实例化对象,调用对象中的方法)

普通的情况:

Activity创建一个view是通过 ondraw 画出来的, 画这个view之前呢,还会调用onmeasure方法来计算显示的大小.

复杂情况:

Surfaceview直接操作硬件子类:opengl .GLSurfaceView

他会将显卡缓存里的内容显示到界面上。

这样速度会比较快,游戏开发经常用到。

MediaPlayer、OpenGL,直接将数据写到显存里,显卡获取显存内容进行显示。

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

这个问题问的有问题, apk包大小限制不好说,这个是根据手机硬件而定的。

极品飞车有100M 还是能装到手机上,

// apk 资源文件素材.

世面上的大程序主程序 很小 5~10M

素材存放在服务器上(也可以下载到sdcard上).如游戏程序.

读大文件的时间限制应该是main线程里面的时间限制5秒.

Service阻塞时间不要超过 20m

Broadcast 10m

37.如何加载的音乐信息,如何改善其效率。

遍历sdcard所有的mp3信息会比较慢,

Mp3 作者信息 专辑 图片 歌词信息

Android提供mediascanner,mediaStore等接口, 音乐文件的信息都会存放到系统的数据库表中,我们可以通过content provider获取音乐信息

如何改善效率(界面显示),是个常见问题, 可以从以下几个方面作答,

分批加载数据, 延时加载数据, 合理使用缓存等...

Java虚拟机,目标,加快java程序执行速度

预先加载一些 都会的使用的大的class的字节码, 提前加载.

时间换时间

空间换时间

38. ListView如何提高其效率?

复用convertview , 历史的view对象

异步加载数据,分页加载数据, onscollLinster();

使用Static class ViewHolder

使用静态的view对象 避免创建过多的view.

也可以把下载后的数据缓存到数据库里

通过客户端和服务器 协同 作战 来实现优化。

图片缓存,检测图片是否失效

通过Http 请求

If-modify-since : 检查数据是否更新如果是302 拿缓存

39.启动应用后,改变系统语言,应用的语言会改变么?

会,老版本sdk不会,新版本会

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

如果在主界面点击图片进入应用程序,则会根据activity在manifest里面的配置,这个activity可能会放在不同的task栈里面

而通过intent跳转:则根据intent的设置来判断是否放在新的任务栈里,如果flag为flag_new_task ,就会放在新的任务栈里。

Receiver、service没有任务栈,要是想启动一个activity,就需要指定flag

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

Android程序用android sdk开发,java程序用javasdk开发.

Android SDK引用了大部分的Java SDK,少数部分被Android SDK抛弃,比如说界面部分,java.awtswing除了java.awt.font被引用外,其他都被抛弃,在Android平台开发中不能使用。

android sdk 还添加了开源工程: httpclient , pullopenGL

将Java 游戏或者j2me程序移植到Android平台的过程中,

AndroidSDK 与Java SDK的区别是很需要注意的地方。

所有的界面的内容,都需要重写,只能保留业务逻辑相关的内容。

1.6的 不支持httpClient的last-modified信息的处理

42.AndroidTask任务栈的分配。

假如有三个Activity A B C,A跳到B,然后B跳到C,现在需要从C跳到A如何传递数据而且使效率最高呢?

首先我们来看下Task的定义,Google是这样定义Task的:a task is what the user experiences as an "application." It's a group of related activities, arranged in a stack. A task is a stack of activities, not a class or an element in the manifest file. 这意思就是说Task实际上是一个Activity栈,通常用户感受的一个Application就是一个Task。从这个定义来看,Task跟Service或者其他Components是没有任何联系的,它只是针对Activity而言的。

Activity有不同的启动模式, 可以影响到task的分配

Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多Activity,Task结束。

如上表所示,是一个实例。从用户从进入邮箱开始,到回复完成,退出应用整个过程的Task栈变化。这是一个标准的栈模式,对于大部分的状况,这样的Task模型,足以应付,但是,涉及到实际的性能、开销等问题,就会变得残酷许多。

比如,启动一个浏览器,在Android中是一个比较沉重的过程,它需要做很多初始化的工作,并且会有不小的内存开销。但与此同时,用浏览器打开一些内容,又是一般应用都会有的一个需求。设想一下,如果同时有十个运行着的应用(就会对应着是多个Task),都需要启动浏览器,这将是一个多么残酷的场面,十个Task栈都堆积着很雷同的浏览器Activity,

是多么华丽的一种浪费啊。

于是你会有这样一种设想,浏览器Activity,可不可以作为一个单独的Task而存在,不管是来自那个Task的请求,浏览器的Task,都不会归并过去。这样,虽然浏览器Activity本身需要维系的状态更多了,但整体的开销将大大的减少,这种舍小家为大家的行为,还是很值得歌颂的

standard", "singleTop", "singleTask", "singleInstance"。

standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。

而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来处理新的Intent(当然,也可以无视...)。这个模式,降低了位于栈顶时的一些重复开销,更避免了一些奇异的行为(想象一下,如果在栈顶连续几个都是同样的Activity,再一级级退出的时候,这是怎么样的用户体验...),很适合一些会有更新的列表Activity展示。一个活生生的实例是,在Android默认提供的应用中,浏览器(Browser)的书签Activity(BrowserBookmarkPage),就用的是singleTop。

singleTask,和singleInstance,则都采取的另辟Task的蹊径。

标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。最典型的例子,还是浏览器应用的主Activity(名为Browser...),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。

singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity,如果涉及到的其他Activity,都移交到其他Task中进行。这使得singleInstance的Activity,像一座孤岛,彻底的黑盒,它不关注请求来自何方,也不计较后续由谁执行。在Android默认的各个应用中,很少有这样的Activity,在我个人的工程实践中,曾尝试在有道词典的快速取词Activity中采用过,

是因为我觉得快速取词入口足够方便(从notification中点选进入),并且会在各个场合使用,应该做得完全独立。

大的apk 拆成 很多小的apk (按照功能拆分,然后搞一个主界面,调用每个功能,然后每个功能的apk的activity都需要在相同的任务栈内运行,这时就需要用到姻缘关系。)

●Activity的android:taskAffinity=""属性 姻缘关系Affinity

1.配置后 当启动这个activity时就先去找有没有activity的亲和力属性相同 有就加入这个activity所在的任务中没有就新开任务

2.affinity起作用需要的条件 必须具备以下任意一个:

1.intent包含FLAG_ACTIVITY_NEW_TASK标记

2.activity元素启用了allowTaskReparenting属性. True(允许任务栈 重定父级)

43.Android中,怎么节省内存的使用,怎么主动回收内存?

尽量多使用内部类 提高程序效率

Bean的字段可以不用 private,直接使用public

回收已经使用的资源,

合理的使用缓存

合理设置变量的作用范围

主动回收:未来的某一段时间执行

System.gc();

44.不同工程中的方法是否可以相互调用?

可以,列举aidl访问远程服务的例子.***

45.Android中是如何实现判断区分电话的状态,去电,来电、未接来电?

Day8 showAddressService.java***

未接来电:是有raning状态直接到idle状态,我们可以记录这俩状态的时间,如果时间间隔过短,就说明是未接。

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

Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面,

每个android程序系统都会给他分配一个单独的liunxuid(user id),

每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程.

47. sim卡的EF文件有何作用 (百度)

Sim卡相关的东西,没接触过

文件规范.

遇到新的知识点,没接触过,不过空着。

我们可以答,通过阅读EF相关文档,可以有所了解。

48.如何判断是否有SD卡?

配置文件中有sd卡的权限, 通过environment的静态方法,

if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

49.嵌入式操作系统内存管理有哪几种, 各有何特性。

内存管理:页式,段式,段页式。

将内存以不同方式,划分成若干份,这样方便管理。

断式分隔,有一块总的汇总索引表,先查找索引,在查找具体哪一块。每一块内存有可能大小不一致。

段需要记录内存空间的引用。消耗了一定空间

页通过计算的方式,去定位特定的内存空间。

50.什么是嵌入式实时操作系统, Android操作系统属于实时操作系统吗?

实时操作系统是指当外界事件或数据产生时,能够接受并以足够快的速度予以处理,其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应,并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、军事设备、航空航天等领域对系统的响应时间有苛刻的要求,这就需要使用实时系统。又可分为软实时和硬实时两种,而android是基于linux内核的,因此属于软实时。

实时操作系统:能够快速响应操作的系统,windows、linux都是。

实时操作系统的原理:

硬实时. 军工系统,火星探测车( Vxworks操作系统) (一旦有一个事件产生,我立马放下所有的事情去执行事件)

软实时.调度算法(当一个事件产生时,根据算法来判断要隔多长时间执行),我们用的一般的系统都是软实时的。

51.一条最长的短信息约占多少byte?

一般情况下是中文70字符(包括标点),英文160个字节

但是根据手机制式运营商的不同,短信长度也不同

做实验,看divideMessage方法的源码

他会判断,手机网络制式去做限制。

52. Linux中跨进程通信的几种方式 。**

linux编程:先了解几个概念。

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

# 有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

# 信号量( semophore ) : 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

# 消息队列( message queue ) : 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

# 信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

# 共享内存( shared memory ) :共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

# 套接字( socket ) : 套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。

53.谈谈对Android NDK的理解。

NDK:native develop kit只是一个交叉编译的工具,调用C代码。

1.什么时候用ndk,实时性要求高,游戏,图形渲染

opencv (人脸识别) , ffmpeg , rmvbmp5 avi 高清解码. ffmpeg, opencore.

2.为什么用ndk,ndk的优点 ,缺点,

优点:效率比较高,复用c代码

缺点:代码编写比较麻烦,问题不好解决

再介绍我们项目中那些地方用到了ndk, c opengl?**

54.谈谈Android的优点和不足之处。不懂技术的人会问。

1、开放性,开源ophone阿里云( 完全兼容android) 乐os

2、挣脱运营商束缚

3、丰富的硬件选择 mtk android

4、不受任何限制的开发商

5、无缝结合的Google应用

缺点也有5处:

1、安全问题、隐私问题

2、卖手机的不是最大运营商

3、运营商对Android手机仍然有影响

4、山寨化严重

5、过分依赖开发商,缺乏标准配置 版本过多

55. Android系统中GC什么情况下会出现内存泄露呢?视频编解码/内存泄露检测内存泄露工具

导致内存泄漏主要的原因是,先前申请了内存空间而忘记了释放。如果程序中存在对无用对象的引用,那么这些对象就会驻留内存,消耗内存,因为无法让垃圾回收器GC验证这些对象是否不再需要。如果存在对象的引用,这个对象就被定义为"有效的活动",同时不会被释放。要确定对象所占内存将被回收,我们就要务必确认该对象不再会被使用。典型的做法就是把对象数据成员设为null或者从集合中移除该对象。但当局部变量不需要时,不需明显的设为null,因为一个方法执行完毕时,这些引用会自动被清理。

Java带垃圾回收的机制,为什么还会内存泄露呢?

Vector v = new Vector(10);

for (int i = 1; i < 100; i++){

Object o = new Object();

v.add(o);

o = null;

}//此时,所有的Object对象都没有被释放,因为变量v引用这些对象。

Java 内存泄露的根本原因就是保存了不可能再被访问的变量类型的引用

Jni开发,可能出现内存泄露:

C代码申请内存,但是没有释放。

公司里 有可能使用内存检测工具:读取源代码,看是否有=null的对象

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

在主线程中拿到view调用Invalidate()方法,查看画画板里面更新imageview的方法

在子线程里面可以通过postInvalidate ()方法;

iv.invalidate();

newThread(){

publicvoidrun(){

iv.postInvalidate();

}

}.start();

57.简单描述下Android数字签名。

Android 数字签名:私有签名**

在Android系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系

Android系统要求每一个安装进系统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。Android将数字证书用来标识应用程序的作者和在应用程序之间建立信任关系,不是用来决定最终用户可以安装哪些应用程序。

这个数字证书并不需要权威的数字证书签名机构认证(CA),它只是用来让应用程序包自我认证的。

同一个开发者的多个程序尽可能使用同一个数字证书,这可以带来以下好处。

(1)有利于程序升级,当新版程序和旧版程序的数字证书相同时,Android系统才会认为这两个程序是同一个程序的不同版本。如果新版程序和旧版程序的数字证书不相同,则Android系统认为他们是不同的程序,并产生冲突,会要求新程序更改包名。

(2)有利于程序的模块化设计和开发。Android系统允许拥有同一个数字签名的程序运行在一个进程中,Android程序会将他们视为同一个程序。所以开发者可以将自己的程序分模块开发,而用户只需要在需要的时候下载适当的模块。

在签名时,需要考虑数字证书的有效期:

(1)数字证书的有效期要包含程序的预计生命周期,一旦数字证书失效,持有改数字证书的程序将不能正常升级。

(2)如果多个程序使用同一个数字证书,则该数字证书的有效期要包含所有程序的预计生命周期。

(3)Android Market强制要求所有应用程序数字证书的有效期要持续到2033年10月22日以后。

Android数字证书包含以下几个要点:

(1)所有的应用程序都必须有数字证书,Android系统不会安装一个没有数字证书的应用程序

(2)Android程序包使用的数字证书可以是自签名的,不需要一个权威的数字证书机构签名认证

(3)如果要正式发布一个Android ,必须使用一个合适的私钥生成的数字证书来给程序签名,而不能使用adt插件或者ant工具生成的调试证书来发布。

(4)数字证书都是有有效期的,Android只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。

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

在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:Application Not Responding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。

Activity 5秒broadcast10秒

耗时的操作 worker thread里面完成,

处理方式:handler message…AsynsTask , intentservice.等…

59. android中的动画有哪几类,它们的特点和区别是什么?

两种,一种是Tween动画、还有一种是Frame动画。

Tween动画,这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;

可以通过布局文件,可以通过代码

1、控制View的动画

a)alpha(AlphaAnimation)

渐变透明

b)scale(ScaleAnimation)

渐变尺寸伸缩

c)translate(TranslateAnimation)

画面转换、位置移动

d)rotate(RotateAnimation)

画面转移,旋转动画

2、控制一个Layout里面子View的动画效果**

a)layoutAnimation(LayoutAnimationController)

b)gridAnimation(GridLayoutAnimationController)

另一种Frame动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。

62.说说mvc模式的原理,它在android中的运用。

MVC英文即Model-View-Controller,即把一个应用的输入、处理、输出流程按照Model、View、Controller的方式进行分离,这样一个应用被分成三个层——模型层、视图层、控制层。

Android中的界面也采用了当前比较流行的MVC框架,在Android中M就是应用程序中二进制的数据,V就是用户的界面。Android的界面直接采用XML文件保存的,界面开发变的很方便。在Android中C也是很简单的,一个Activity可以有多个界面,只需要将视图的ID传递到setContentView(),就指定了以哪个视图模型显示数据。

在Android SDK中的数据绑定,也都是采用了与MVC框架类似的方法来显示数据。在控制层上将数据按照视图模型的要求(也就是Android SDK中的Adapter)封装就可以直接在视图模型上显示了,从而实现了数据绑定。比如显示Cursor中所有数据的ListActivity,其视图层就是一个ListView,将数据封装为ListAdapter,并传递给ListView,数据就在ListView中显示。

63.通过点击一个网页上的url就可以完成程序的自动安装,描述下原理

Android基础:Day11AddJavascriptInterface**

通过javascript调用java代码

64.ServiceActivity在同一个线程吗

默认情况同一线程 main主线程 ui线程

65.java中的soft reference是个什么东西

StrongReference 是 Java 的默认引用实现, 它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收

SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合内存缓存

66.udp连接和TCP的不同之处

Tcp:就像打电话,滑动窗口协议. 拥塞控制.

udp 不关心数据是否达到,以数据包的形式传递。是否阻塞

qq视频:

画面优先. tcp

流畅优先udp

qq发信息:udp,但是有时候会出现 某信息 未送达的提示,这是qq发信息的同时,会等待回执信息(udp发送),如果接受到这个信息,就说明发送成功。

如果没有接受到,就说明发送失败,但有时候对方收到了,却提示自己发送失败,原因是这个回执信息在发送过程中丢失了。

67. android开发中怎么去调试bug

逻辑错误

1.断点 debug

2. logcat

界面布局错误,使用 hierarchyviewer.bat ,显示布局层级的工具

我们可以使用这个工具,去分析别人的界面,然后借鉴

68.service里面可以弹土司么

可以

69.10个简单的linux命令

cat ls ps psw wc mv rm cd ping tracert find grep tail vi gcc make ifconfig

startup dhcp

chmod

70 .JNI调用常用的两个参数

JNIEnv *env, jobject javaThis记住即可

71.书写出android工程的目录结构

记住即可:

src

android.jar

asset

res

gen

manifest

72. ddmstraceview的区别.

daivilk debug manager system

查看进程、查看文件、模拟电话、短信,gps定位等等。

traceview 分析程序执行时间和效率代码优化时使用

使用步骤:

1.在应用的主activity的onCreate方法中加入Debug.startMethodTracing("xxx.trace");

2.同样在主activity的onStop方法中加入Debug.stopMethodTracing();

3.同时要在AndroidManifest.xml文件中配置权限

3.重新编译,安装,启动服务,测试完成取对应的traceview文件(adb pull /sdcard/xxxx.trace)。

4.直接在命令行输入traceview xxxxtrace,弹出traceview窗口,分析对应的应用即可。

在这个文件中,可以分析出所有代码执行过程中,cpu的消耗情况,占用时间。

公司常用素语:

KPI : key performance information : 关键性能指标:

指标:如splash界面不能超过5秒

从splash 界面加载mainactivity 不能超过0.7秒

73.同步异步的理解,什么是同步,什么是异步,多次调用异步方法会出现什么问题.

同步就是你叫我去吃饭,我听到了就和你去吃饭;如果没有听到,你就不停的叫,直到我告诉你听到了,才一起去吃饭。

异步就是你叫我,然后自己去吃饭,我得到消息后可能立即走,也可能等到下班才去吃饭。

所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。

多次调用异步方法:未来一段时间内,得到多次响应

图片乱跳:**就是这个

以通讯为例

同步:发送一个请求,等待返回,然后再发送下一个请求

异步:发送一个请求,不等待返回,随时可以再发送下一个请求

并发:同时发送多个请求

74.利用mvc的模式重构代码

1)重构前的代码Bmi.java:

packagecom.demo.android.bmi;

importjava.text.DecimalFormat;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.EditText;

importandroid.widget.TextView;

publicclassBmiextendsActivity {

/** Called when the activity is first created. */

@Override

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// Listen for button clicks

Button button = (Button) findViewById(R.id.submit);

button.setOnClickListener(calcBMI);

}

privateOnClickListenercalcBMI=newOnClickListener() {

@Override

publicvoidonClick(View v) {

DecimalFormat nf =newDecimalFormat("0.00");

EditText fieldheight = (EditText) findViewById(R.id.height);

EditText fieldweight = (EditText) findViewById(R.id.weight);

doubleheight = Double.parseDouble(fieldheight.getText().toString()) / 100;

doubleweight = Double.parseDouble(fieldweight.getText().toString());

doubleBMI = weight / (height * height);

TextView result = (TextView) findViewById(R.id.result);

result.setText("Your BMI is "+ nf.format(BMI));

// Give health advice

TextView fieldsuggest = (TextView) findViewById(R.id.suggest);

if(BMI > 25) {

fieldsuggest.setText(R.string.advice_heavy);

}elseif(BMI < 20) {

fieldsuggest.setText(R.string.advice_light);

}else{

fieldsuggest.setText(R.string.advice_average);

}

}

};

}

Step1抽取所有界面元件的声明和定义,整合到单独一个函数findViews()中;

//声明view

privateButtonbutton_calc;

privateEditTextfield_height;

privateEditTextfield_weight;

privateTextViewview_result;

privateTextViewview_suggest;

//定义

privatevoidfindViews() {

button_calc= (Button) findViewById(R.id.submit);

field_height= (EditText) findViewById(R.id.height);

field_weight= (EditText) findViewById(R.id.weight);

view_result= (TextView) findViewById(R.id.result);

view_suggest= (TextView) findViewById(R.id.suggest);

}

此部分即是MVC中的V:View视图。

Step2抽取程序的逻辑(即界面元件的处理逻辑),整合到函数setListensers()中;

//Listen for button clicks

privatevoidsetListensers() {

button_calc.setOnClickListener(calcBMI);

}

此部分即是MVC中的C:Controller控制器。

接着,onCreate()就显得非常简洁、明了了:

publicvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

findViews();

setListensers();

}

Step3修改按钮监听器calcBMI中相应的部分(主要是变量已经在视图部分定义了);

privateOnClickListenercalcBMI=newOnClickListener() {

@Override

publicvoidonClick(View v) {

DecimalFormat nf =newDecimalFormat("0.00");

doubleheight = Double.parseDouble(field_height.getText().toString()) / 100;

doubleweight = Double.parseDouble(field_weight.getText().toString());

doubleBMI = weight / (height * height);

// Present result

view_result.setText("Your BMI is "+ nf.format(BMI));

// Give health advice

if(BMI > 25) {

view_suggest.setText(R.string.advice_heavy);

}elseif(BMI < 20) {

view_suggest.setText(R.string.advice_light);

}else{

view_suggest.setText(R.string.advice_average);

}

}

};

总之,此重构的目的无非是使程序的脉络更加清晰,即让人一眼望去,就能很容易地分辨出界面(View)应该写在哪里,程序逻辑(Controller)应该写在哪里,最终使维护和扩展代码变得更加容易!

其实,重构很简单,通读代码,感觉哪边不太爽,就改那边吧!(我目前的感受)

一个良好的代码应该是能让人感到舒服的!

总结:

关于项目

在就是你项目经验,一定要突出你遇到什么难点,然后是怎么解决的!把问题引导到你熟悉的领域,或者知识点上,尽量将每个技术点细节凸显出来,

心态:

什么样的面试官都有,去面试的时候要做好一切心理准备,不管是技术还是基础都得扎实。一个人的交谈能力也很重要,总之不是非常标准的普通话, 最起码你说的得让别人听得懂,而且得把面试官讲得非常彻底,这样你获得offer的机会更大,谈工资也有优势~~

你可能感兴趣的:(android面试,那些年我们遗忘的基础)