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

Android面试题整理

2016-06-05 15:58 609 查看
1. 什么是Activity?

是一个可以与用户交互的屏幕,例如打电话、拍照、地图、日历的界面

An Activity is
an application component that provides a screen with which users can interact in order to do something, such as dial the phone, take a photo, send an email, or view a map.

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

1) 对象从创建到销毁有哪些状态

创建、运行、暂停、停止、销毁、 可见可操作 可见不可操作 不强制结束

可见

2) 状态之间的切换会触发哪些方法

3) 当某个更高优先级的进程中的Activity启动

状态/状态切换触发方法

1. 加载

2. 运行 onCreate() onStart() onResume()

3. 暂停 onPause

4. 停止 onStop

5. 关闭 onDestroy

当Activity处于暂停或停止状态时,可能被强制结束

进程优先级:5

1. Activity startForeground

2. Paused

3. background startservice

4. onStop Activity

5. empty 为了下次更快启动继承

举例说明

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

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

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

其实这些方法都是两两对应的,onCreate创建与onDestroy销毁;

onStart可见与onStop不可见;onResume可编辑(即焦点)与onPause;

对话框的弹出, Activity.this

对话框是activity的一部分.

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

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

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

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

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

多媒体播放, 播放来电话. onStop() 视频, 视频声音设置为0 , 记录视频播放的位置 mediaplayer.pause();

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

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

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

A:onPause onStop

B:onCreate onStart onResume

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

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

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

清单没有配置:重新创建配置,

configChanges=keyboardhidden|orientation|screeSize”

screenOrientation=”port”

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

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

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

Onpause onstop ondestory oncreate onstart onresume

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

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

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

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

onSaveInstanceState()
1.Home
2.长按Home
3.按下电源键
4.一个activity启动另外一个activity(onCreat())
5.屏幕切换的时候

onRestoreInstanceState
Activity被系统kill.

onSave

onRestore

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

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

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

1、抛异常强制退出:

该方法通过抛异常,使程序Force Close。

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

//安全结束进程

android.os.Process.killProcess(android.os.Process.myPid());

System.exit(0)

2、记录打开的Activity:

Class MyApplication extends Application

{

Private List<Activity> lists = new List<Activity>();

Private MyApplication()

{

}

Public static MyApplication()

{

}

每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。

List<Activity> lists ; 在application 全集的环境里面

lists = new ArrayList<Activity>();

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

Ondestory() lists.remove(this);

lists.add(activity);

for(Activity activity: lists)

{

activity.finish();

}

3、发送特定广播:

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

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

registerReceiver(receiver, filter)

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

4、递归退出

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

404 退出程序

OnActivityResult();

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

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

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

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

IntentService

Onhandler()

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

让service在另外的进程中执行

<service

android:process="cn.itcast.xxx"></service>

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

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

extras.putDouble(key,value)

intent.putExtra(name, value)

// 通过intent putExtra方法基本数据类型都传递

Bundle bundle = new Bundle();

bundle.putShort(key, value);

intent.putExtras(bundle);

intent.putExtras(bundle)

获取到激活他的 getIntent();

Intent intent = getIntent();

Bundle bundle = intent.getExtras();

Bundle 类似map的集合

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

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

Application 全局里面存放 对象 ,自己去实现自己的application的这个类,基础系统的application , 每个activity都可以取到

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

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

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

FileOutputStream fos =new FileOutputStream(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

Parcelable 把对象序列化到android操作系统的一块公用的内存空间

文件/网络

//传递数据的引用

10. 怎么样在启动一个Activity时就启动一个service?

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

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

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

singleinstance

单独的任务栈

Intent的flag添加FLAG_ACTIVITY_NEW_TASK

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

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

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

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

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

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

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

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

构建一个intent对象,

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

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

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

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

private class myconn implements ServiceConnection

{//异步的操作, 可能需要花费若干秒的时间

public void onServiceConnected(ComponentName name, IBinder service) {

// TODO Auto-generated method stub

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

}

public void onServiceDisconnected(ComponentName name) {

// TODO Auto-generated method stub

}

}

14 .什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停用Service?

在Service的生命周期中,被回调的方法比Activity少一些,只有onCreate, onStart, onDestroy,

onBind和onUnbind。

A Service is
an application component that can perform long-running operations in the background and does not provide a user interface.

通常有两种方式启动一个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的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. 不用service,B页面为音乐播放,从A跳转到B,再返回A,如何使音乐继续播放?

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

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

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

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

是单线程消息队列处理模型
功能:一个线程处理多个任务,是对Handler、MessageQueue、Looper的封装
优点:使用简单,不需要理解Handler、MessageQueue、Looper概念

17. 什么时候使用Service?

必须使用音乐后台播放

输入法

没有界面的后台服务,它可以在后台运行,比如音乐播放、下载可以使用Service

启动方式、生命周期

拥有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生命周期 和 响应时间很短

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

2015-12-08 Android

请描述一下Intent 和 Intent Filter。

Activity、Service和BroadcastReceiver

Intent.FLAG_ 加载模式

显式 隐式

Intent条件

Action

Category

Data

type

Intent:定义 三大组件消息传递的纽带,分为显式和隐式

明确指定启动的组件名,隐式不明确但指定条件,

什么是Intent、Intent的作用,三大组件之间传递消息,分为隐式和显式,隐式和显式的概念和区别,Intent-Filter,用来包装隐式意图过滤条件的

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

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

Intent filter: 可以理解为邮局或者是一个信笺的分拣系统…

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

Action: 动作 Intent.ation_view

Data: 数据uri uri mime

Category : 而外的附加信息

Action 匹配

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

<intent-filter >

<action android:name="android.intent.action.MAIN" />

<action android:name="cn.itcast.action" />

……

</intent-filter>

如果我们在启动一个 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 携带外部数据给目标组件。在 <intent-filter >节点中,通过 <data/>节点匹配外部数据。

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

<data android:mimeType="mimeType" android:scheme="scheme"

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

电话的uri tel: 12345 package:cn.itcast.xxx
http://www.baidu.com
自己定义的uri itcast://cn.itcast/person/10

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

Category 类别匹配

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

默认是DEFAULT

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

基本类型

String

对象:Serializable Parcelable

以上所有类型的数组(除了Serializable)

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

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

20. 说说Activity,Intent,Service是什么关系 。

Activity启动Service需要通过Intent

麦当劳和麦当娜的关系是什么关系?

这种问题,就讲下activity,讲一下service,说一下 通过intent去激活组件,传递数据.

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

开启服务用的是intent来开启

21. 请描述一下Broadcast Receiver。

定义:接收自己或其他App发送的Broadcast

好处:群发消息

使用:code XML

广播分类:无序、有序

回答问题的思路:

1. 是什么

2. 功能/作用/好处

3. 如何使用

各种实现方式的区别

概念:

是什么:接收广播消息, 自己发,

系统发:接收到外部事件,发送广播消息

广播分为:无序(并行) 有序(串行)

intent-filter android:priority="3000’

abortbroadcast();

广播 android操作系统的一个事件

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

广播分两种

有序广播

无序广播

指定接收者的广播 . 是不可以被拦截掉的

<intent-filter android:priority="1000"> 那个程序的uid 越低 越先接受到消息

<action android:name="android.provider.Telephony.SMS_RECEIVED"/>

</intent-filter>

onReceive() 方法.

abortBroadcast();

有序广播有一个特例

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

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

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

SetresultData();

Sticky

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

Wifi设置

用于接收系统的广播通知, 系统会有很多sd卡挂载,手机重启,广播通知,低电量,来短信等,一个apk的安装成功….

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

<intent-filter android:><action> sms_received </action></intent-filter>

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

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

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

sendBroadcast(intent);

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

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

详细见工程代码.

<intent-filter android:priority="1000">

<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>

</intent-filter>

</receiver>

<receiver android:name=".SmsReceiver">

<intent-filter android:priority="1000">

<action android:name="android.provider.Telephony.SMS_RECEIVED"/>

</intent-filter>

</receiver>

<receiver android:name=".BootCompleteReceiver">

<intent-filter>

<action android:name="android.intent.action.BOOT_COMPLETED"/>

</intent-filter>

</receiver>

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

registerReceiver(receiver,filter);



Android 01-14 Android

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

1. Class MyProvider extends ContentProvider

2. ORM方式实现数据库,SQLiteOpenHelper

Uri: “content://authorities”

getContentResolver().query(uri)

URL

URI

1) 如何创建provider

2) 数据库的用法

把自己的数据通过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

技巧: 1.看urlmarcher.

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

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

五个

存储路径、使用场景、区别

1) SharedPreferences

ROM

/data/data/packagename/shared_prefs/

Xml

场景:私有的、少量的键值对形式的数据,应用程序的设置

2) InternalStorage

ROM

/data/data/packagename/files/xxx.xxx

文件格式和内容任意,OpenFileInput

3) ExternalStorage

SdcardI/O

判断SD状态 是否加载、空间是否足够

Environment.getExternalStorageDirectory()

大型游戏数据包和地图导航

4) SQLite

ROM

/data/data/packagename/databases/

class MyDB extends SQLiteOpenHelper

MyDB()

onCreate

onUpgrade

应用场景:大量结构类似的数据,经常进行增删改查

5) Web

Get Post

应用场景:多个客户端同步

云笔记本

文件 访问权限. sdcard

/data/data/包名/files 内存里面

<data>/<data>context.openFileInput(name)默认是私有的访问权限

数据库 sqlite

SharedPreference <data>/<data>/包名/shared_preps Context.modeprivate

网络 socket tcp 面向连接 打电话 udp 平信 udp,

http httpurlconnection

Android httpclient post get

ftp的网络 file transport protocol

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

Android数据存储有5中方式,统一数据共享接口,ContentProvider

屏蔽数据存储的细节,对用户透明,用户只需要关心操作数据的uri就可以了,对应的参数 .

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

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

网络数据读取更改

Sql也有增删改查的方法.

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

Linear orientation weight layout_gravity

Relative alignparent alignLeft above

Frame layout_gravity

Table

Absolute

每个布局的特性和他们的区别

27. 谈谈UI中, Padding和Margin有什么区别?

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

29. 请解释下在单线程模型中Message、Handler、Message Queue、Looper、Thread之间的关系。

自定义消息处理队列,一个线程处理在一个队列里的多个消息

Message 封装消息

Handler 两个线程间发送

MessageQueue 保存Message 队列 先进先出

Looper 从MessageQueue中取消息(当线程空闲时)

Thread 处理消息

创建:new Thread()

{

public void run()

{

Looper.prepare();//创建了Looper和MQ

Handler = new Handler()

{

handleMessage(Message msg){};

};

Looper.loop();

}

}.start()

运行:

Activity 里面默认会帮创建Looper

子线程里面 显示土司

Looper.parepare();

Toast

Looper.loop();

2016-05-19 Android

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

Android IDL Interface Definition Language

功能:进程间通讯

Activity

Service

Innerprocess Communication
进程间通讯

Android Interface Definition Language

SQL Structured Query Language

XML eXtensible Markup Language

HTML HyperText Markup Language

基于Activity绑定Service

步骤:1) 创建。Aidl文件

创建interface,写方法,改扩展名 public删除

2) 拷贝到另一个项目,包名必须一致

3) Service: extends XXX.stub

4) Activity:XXX.stub.asInterface()

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

用来跨进程的访问方法,

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

.endcall();

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

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

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

-rw------ 私有权限 -rw-rw-rw- 全局可读可写 linux系统的文件权限

文件系统的权限是linux权限. 比如说sharedpreference里面的Context.Mode_private

Context.Mode.world_read_able Context.Mode_world_writeable

777自己 同组 其他

root 是危险的行为

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

Intent .setAction(VIEW)

setData("http://")

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

Intent intent = newIntent();

// com.android.browser/.BrowserActivity

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

Intent.setdata(uri);

queryintentactivity(); 推广自己产品的操作

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

概念: 举例

好处

功能作用 创建View 更新View 事件处理

用法

注意事项

Main线程的功能:创建UI、更新UI、事件处理

要求:耗时操作如果超过5s,有可能性产生ANR

onReceive()清单中注册 10s

主ui线程不能执行耗时的操作,

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

Dalvik 基于寄存器 .dex (多个class)

JVM 基于堆栈 .class (一个class)

内存管理机制: Object Heap (应用程序大小) 最小2M 最大16M

Bitmap Meorrey 图片处理

Native heap 不限制大小

垃圾回收机制:对垃圾回收机制调优 (JIT编译器)

AOT

5ms

4.4 art

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

谈谈加载图片的时候怎么处理大图片的,

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

System.gc(); 不是立刻去执行垃圾回收.

Moblietv 获取300 30K 频道.icon gallery

手机电视. 视频点播. Onstop() 通知gc();

别的界面图片 白板.

遇到一个不可复现的bug, 不解决 won't fix

乐观锁 悲观锁

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

向下调用底层.向上就是为app提供API\系统服务
JNI (反射)

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

Architecture&Designer

Programmer 领域框架 广告SDK 登录SDK

coder

反射 , 配置文件 Jolt

Coder->Programmer 敏捷开发、原则模式与实践

面向对象的设计原则OOAD

重构Refactor

修改代码的艺术

设计模式

领域驱动设计

管理 工程

作坊 CMMI 敏捷开发

可以讲下activity的源码,比如说 每个activity里面都有window.callback和keyevent.callback,一些回调的接口或者函数吧. 框架把activity创建出来就会调用里面的这些回调方法,会调用activity生命周期相关的方法.

setContentView();

普通的情况:

Surfaceview 直接操作硬件 opengl .GLSurfaceView

图像要想被显示到界面上, 需要设备显卡, 显存.

写到显存.

Mediaplayer

Opengl

直接把数据写到显存.

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

系统会在启动或者SDCard变更时扫描存储器,ROM和SDCard

并将结果写入数据库

.nomedia

MP3播放器. 遍历sd卡的mp3

Mp3 作者信息 专辑 图片 歌词信息 id3 id3v1 id3v2

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

显示出来,改善效率,是个常见问题, 可以从以下几个方面作答,

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

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

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

时间换时间

空间换时间

37. ListView如何提高其效率?

Bg背景 cachecolorhint

1. 行布局复用convertView

2. 图片内存缓存

3. ViewHolder减少查找控件次数

4. 延迟加载LazyLoad 可见加载

5. 高度设为match

6. 数据封装

7. 异步加载 AsyncLoad

8. 图片外存缓存

9. 分页加载

性能优化

convertView

ViewHolder

高度改为match

图片缓存

只更新显示的行 LazyLoad

提高可读性可维护性

数据封装

Convertview

viewHolder

异步加载图片

内存缓存

SDcard缓存

延迟加载

复用convertview , 历史的view对象

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

Static class ViewHolder

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

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

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

取决于是否做了国际化

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

1. 点图标是新的栈 Task

2. 如果隐式意图中带有flag_activity_new_task

那么是新的栈,否则在启动它的组件所在栈中

区别是根据activity在manifest里面的配置,这个activity可能会放在不同的task栈里面

intent设置的flag flag_activity_new_task



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

Android App JAVASE Swing JAVA EE

相同:1. 语言

2. 碎片化 Android App Swing 网页

不同:1. 虚拟机 Dalvik VM JVM

2. 框架 Android EJB SSH JFinal

3. 文件形式 apk jar war

4. 跨进程

5. 领域 移动App PC App Web后台

6. Android SDK + Java SDK JDK JAVAEE SDK

7. 数据持久化方式5 数据库

8. Class打包 .dex .class

9.

相同:语言

不同:

1. ADT SwingDesigner

2. Linux 跨平台

3. UI客户端 JAVASE Swing 客户端 JAVAEE 服务端

4. Dalvik JVM (IBM HP)

5. 语言版本 JAVA5.0语法 去掉了swing

JAVA 1.8

6. .dex .jar

C/S Client Server

B/S Browser Server

UI 数据

Html+js

1. 运行环境:Dalvik VM JVM

2. 应用领域:端 云

3. API 语法1.5 1.8

4. 开发 ADT MyEclipse

5. 编译 .dex apk class jar

6. 硬件 智能终端 服务器

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

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

android sdk 添加工具jar httpclient , pull openGL

42. Android中Task任务栈的分配。

Task Activity的加载模式

默认:以栈的形式添加Activity

standard

singleTop

singleTask onNewIntent()

singleInstance

举例

假如有三个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栈(粗体为栈顶组件)

点开Email应用,进入收件箱(Activity A)

A

选中一封邮件,点击查看详情(Activity B)

AB

点击回复,开始写新邮件(Activity C)

ABC

写了几行字,点击选择联系人,进入选择联系人界面(Activity D)

ABCD

选择好了联系人,继续写邮件

ABC

写好邮件,发送完成,回到原始邮件

AB

点击返回,回到收件箱

A

退出Email程序

null

如上表所示,是一个实例。从用户从进入邮箱开始,到回复完成,退出应用整个过程的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

Andorid 车载电脑:

组网领航 事故急救

140M apk

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

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

activity所在的任务中没有就新开任务

2.affinity起作用需要的条件而者具备一个:

1.intent包含FLAG_ACTIVITY_NEW_TASK标记

2.activity元素启用了allowTaskReparenting属性.true

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

Bitmap.recycle

软引用

SoftReference

weakReference

图片压缩

清除

延迟加载

外存

资源池

节省内存:1. 缓存 2. 外存 3. 延迟加载

4. 资源池

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

Bean private public

回收已经使用的资源,

合理的使用缓存

合理设置变量的作用范围 application 对象

//未来的某一段时间执行

System.gc();

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

1. 库 2. aidl

可以。1. Jar包 2. Library 3. AIDL

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

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

Aidl 挂断、接听

PhoneStatelistener

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

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

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

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

1-15 Android

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

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

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

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

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

硬实时. 火星探测车 Vxworks

软实时. 调度算法

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

linux编程

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

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

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

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

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

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

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

53. 谈谈对Android NDK的理解。

JNI java Native Interface

Why:必要性: EA 大型游戏 C++ 大型游戏移植

包含:库 doc 工具 例子

作用:Android应用中可以使用本地代码

如何使用:android ndk

.so .dll

XDK: 必须:库 rt.jar android.jar

辅助:例子、源代码、doc、可执行文件、工具

c C++--》so

NDK:库 c和C++库例子 源代码 文档 工具

功能:Android中可以使用c或C++实现某些功能

编译:cygwin

应用场景:大量数据运算、3D游戏

误区:为了提升效率而使用NDK

容易导致应用崩溃

native develop kit 只是一个交叉编译的工具 .so

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

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

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

我们项目中那些地方用到了ndk, c opengl

54. 谈谈Android的优点和不足之处。

1. GooglePlayService

2. Google Music

优点:

1.可定制

2. 开源

3. 免费

4. 用户量大 10亿 80%

5. 应用量大

不足:

1. 安全性

2. 碎片化

3. 性能

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 开发可能会出现内存泄露

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

Main线程负责更新UI,外部调用view的invalidate()方法,onDraw()方法会被出发

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

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

iv.invalidate();

new Thread(){

publicvoid run(){

iv.postInvalidate();

}

}.start();

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

为什么:

1. 保证在同一个Android系统中,相同包名不同签名的apk无法覆盖安装

2. 证明开发者身份

3. 防止抵赖

概念:对应用的设置的数字标识

作用:防抵赖、更新(包名和签名都相同)、必须有签名

怎么用:eclipse Android tools

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 如何避免它?

Activity not respond

耗时操作:HTTP SDCard IO ROM

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

Activity 5秒 broadcast10秒

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

handler message…AsynsTask , intentservice.等…

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

PropertyAnimation优点:

1) Tween是视图的改变,控件本身没有改变

Property真正改变控件

2) 很容易实现纵向移动,曲线移动

3) 功能更强大

Tween:通过改变图形的大小、位置、透明度、角度

Frame:类似gif,多张图片快速切换

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

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

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

1、控制View的动画

a)alpha(AlphaAnimation)

渐变透明

b)scale(ScaleAnimation)

渐变尺寸伸缩

c)translate(TranslateAnimation)

画面转换、位置移动

d)rotate(RotateAnimation)

画面转移,旋转动画

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

a)layoutAnimation(LayoutAnimationController)

b)gridAnimation(GridLayoutAnimationController)

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

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

MVC-->MVP-->MVVM

Model(模型 数据SQLite) DBA 数据库工程师

View(视图 View) 前端工程师 htm + css + js

Control(控制 Activity Adapter) JAVA EE

Listview MVC

M arraylist

View listview

Control adapter

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 就可以完成程序的自动安装,描述下原理

静默安装:

http://www.apkbus.com/android-120895-1-1.html

搜索:编译android源码

Day11 AddJavascriptInterface

new Object{

callphone();

installapk();

}

64,Service和Activity在同一个线程吗

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

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

SoftReference<String> refer = new SoftReference<String>(new String("sdf"));

String string = refer.get();

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

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

应用详细见豆瓣客户端图片的缓存

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

网页 html + js 静态

网站 JAVAEE/.net/PHP/python/RoR ruby

网络 UDP TCP SOCKET

Server Client

TCP 长连接 类似打电话 数据可达

UDP 短连接无状态 类似广播 不保证可达

UDP: 不需要保持连接 无法保证消息准确送达

TCP/IP:长连接,消息准确送达

Http

Socket

udp 不关心数据是否达到,是否阻塞 数据包 平信

qq视频

画面优先. tcp

流畅优先 udp

qq发消息 , udp

应用层上 包装数据 一定要发送.

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

找bug

打印日志 log

断点调试

Bug级别:

1. FC

2. 不会FC,没有达到预期效果(环境问题)

2.1) 按照流程,假设重做关键步骤

2.2) 缩小问题所在范围

3. 乱码

客户端 + 服务端 + 源代码(资源文件)编码 都是utf-8

4. 自定义控件

5. 性能

具体类别:

1. R文件

2. 多个库Jar包冲突

3. Android编译版本

4.

逻辑错误

1.断点 debug

2. logcat ,

界面布局,显示 hierarchyviewer.bat

68.service里面可以弹Toast么

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

Src

Gen

Libs

Bin

Assets原始内容,不会编译为二进制

文件夹

Res

Raw 不会编译为二进制 R

Anim tween

Drawable selector shape frame bitmap

Drawable-xdpi png jpg gif bmp

Layout

Values string style theme dimen attr array color

Menu

Color selector 文字颜色

Xml preferences appwidget

Raw 原始内容,不会编译为二进制

Androidmanifest

72. ddms 和traceview的区别.

daivilk debug manager system

1.在应用的主activity的onCreate方法中加入Debug.startMethodTracing("要生成的traceview文件的名字");

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

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

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

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

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

traceview 分析程序执行时间和效率

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

splash界面不能超过5秒

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

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

同步:多个线程访问某个资源先后执行

异步:多个线程同时执行,互相没有先后顺序

如果使用AsyncTask,会导致线程池超出,FC

每个线程占用内存较多,OOM

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

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

package com.demo.android.bmi;

import java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

publicclass Bmi
extends
Activity {

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

@Override

publicvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

// Listen for button clicks

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

button.setOnClickListener(calcBMI);

}

private OnClickListenercalcBMI =
new OnClickListener() {

@Override

publicvoid onClick(View v) {

DecimalFormat nf = newDecimalFormat("0.00");

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

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

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

double weight = Double.parseDouble(fieldweight.getText().toString());

double BMI = 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

private Button
button_calc;

private EditText
field_height;

private EditText
field_weight;

private TextView
view_result;

private TextView
view_suggest;

// 定义

privatevoid findViews() {

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

privatevoid setListensers() {

button_calc.setOnClickListener(calcBMI);

}

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

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

publicvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

findViews();

setListensers();

}

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

privateOnClickListenercalcBMI =newOnClickListener() {

@Override

publicvoid onClick(View v) {

DecimalFormat nf = newDecimalFormat("0.00");

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

double weight = Double.parseDouble(field_weight.getText().toString());

double BMI = 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)应该写在哪里,最终使维护和扩展代码变得更加容易!

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

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

2) 重构后的代码Bmi.java:

package com.demo.android.bmi;

import java.text.DecimalFormat;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

publicclass Bmi
extends
Activity {

private Button
button_calc;

private EditText
field_height;

private EditText
field_weight;

private TextView
view_result;

private TextView
view_suggest;

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

@Override

publicvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

findViews();

setListensers();

}

// 定义

privatevoid findViews() {

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);

}

// Listen for button clicks

privatevoid setListeners() {

calcbutton.setOnClickListener(calcBMI);

}

private Button.OnClickListenercalcBMI =
new Button.OnClickListener() {

publicvoid onClick(View v) {

DecimalFormat nf = newDecimalFormat("0.0");

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

double weight = Double.parseDouble(field_weight.getText().toString());

double BMI = weight / (height * height);

// Present result

view_result.setText(getText(R.string.bmi_result) + 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);

}

}

};

}

Android中的线程、进程和消息处理机制

应用程序的启动运行就是一个进程的触发,我们知道进程是由线程组成的。Handler是Android中用来进行线程间的通信的。

1)android进程分类

a.前台进程是用户当前正在使用的进程。只有一些前台进程可以在任何时候都存在。只有在系统内存无法维持当前进程运行时才会被结束,也可以手动降级(即关闭)。

如果有以下的情形的那么就是前台进程:

这个进程运行着一个正在和用户交互的Activity(这个Activity的onResume()方法被调用)。

这个进程里有绑定到当前正在和用户交互的Activity的一个Service。

这个进程里有一个onReceive()方法的BroadCastReiver对象。

b.可见进程是没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。

如果一个进程满足以下任一条件,即视为可见进程。

不在前台、但仍对用户可见的Activity(已调用其onPause() 方法)。例如,如果前台Activity 启动了一个对话框。

托管绑定到可见(或前台)Activity的 Service

可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。

c.服务进程是正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如,在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。

d.后台进程是目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。这些进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供前台进程、可见进程或服务进程使用。

e.空进程是为了再次运行提高速度,不用开辟进程空间,只需将数据装载进来就可以了。

2)进程的优先级

Android为了管理内存释放有限的空间,会根据优先级杀死优先级低的进程。从高到低依次为:

空进程—>后台进程—>服务进程—>可见进程—>前台进程

3)Android线程

a)Android是单线程模式

b)Android进程在启动时,会创建一个主线程(UI线程)去处理UI相关操作,为了高效率考虑,主线程不是线程安全的。

当一个程序第一次启动时,ANDROID会同时启动一个对应的主线程(MAIN THREAD),主线程主要负责处理与UI相关的事件,如用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理。所以主线程通常又被叫做UI线程。

什么叫线程不安全呢?如果主线程在处理UI的时候子线程也想处理UI将导致主线程阻塞。

c)子线程不能直接操作主线程内的控件,UI控件只能由UI线程去操作。

d)若要实现线程间通信,需要依赖于Android消息机制等技术

4)Handler

Android消息机制,如果子线程需要处理UI控件,必须借助Handler发送消息给主线程,由主线程完成处理操作(这里需要注意,子线程中发送的消息其实就是一个消息Message,我一开始以为要发送一个意图,把自己想做的处理发给主线程,实际上仅仅是发送一个“提醒”,当然可以附带数据,然后具体处理UI还是在主线程中写代码。我的意思是,如果我想让你帮我做件事,我只说帮我做件事,但不说做什么事,你却做了一件具体的事。)。

Handler 的使用涉及到四个组件:Message、MessageQueue、Looper、Handler

Message:消息,线程通信中携带标记信息和数据信息

MessageQueue:消息队列,子线程发给主线程的消息可能有多个,但不能同时处理,把消息按先后顺序存放,挨个取出执行

Looper:消息管理者,Looper以无限循环的模式不断从消息队列中取出消息并传给Handler

Handler:消息处理者,通过Handler发送消息,亦通过Handler处理消息

如何使用:

子线程发消息到主线程:

在主线程中新建一个Handler对象;

在子线程中使用主线程中创建的Handler对象发送一个消息(消息中需要包含数据和标识信息);

在主线程中的Handler对象中重写handlerMessage()方法,在该方法中写入需要进行的UI操作。

主线程发消息到子线程:

在子线程中获取当前线程的Looper(主线程不需要手动获取)Looper.prepare()

在子线程中新建Handler对象

在主线程中获取子线程中的Handler对象并发送一个消息

在子线程Handler类中重写handlerMessage()方法,在该方法中写入需要进行的操作

在子线程中启动Looper:Looper.loop()

关于Message的新建:

Message message = new Message();

MessageQueue(消息队列)中最多存在50个消息,官方建议不使用创建的方法新建。如果消息很多,每个消息都新建一个新的消息,数量足够多将导致垃圾过多内存溢出。

Message message = Message.obtain();

obtain()方法中会对消息队列中使用过的消息进行判空,如果有用过的消息就将新消息赋值给它,如果没有才新建消息。

handler.obtainMessage()方法与Message.obtain()相似,前者其实回调了后者,效果相同

Message对于信息的携带

可同时携带三个整型和一个Object类型数据(arg1,arg2,what,obj)

其中what是一个唯一标识本条信息的数据,一般以16进制形式赋值。

此外,还可以通过以下方法新建Message

Message message = Message.obtain(handler,what, obj);

Message message = Message.obtain(handler,what, arg1,arg2);

Message message = Message.obtain(handler,what, arg1,arg2,obj);

这些方法都对Message做了不同程度的封装,使用起来更加方便

Handler发送消息

handler.sendEmptyMessage(what)发送即时空消息

handler.sendEmptyMessageAtTime(what,uptimeMillis)特定时间发送空消息

handler.sendEmptyMessageDelayed(what,delayMillis)特定延迟发送空消息

空消息甚至不需要新建Message,直接在方法中填入what值

handler.sendMessage(message)发送即时消息

handler.sendMessageAtTime(message,uptimeMillis)特定时间发送消息

handler.sendMessageDelayed(message,delayMillis)特定延迟发送消息

Handler接收并处理消息

handleMessage(Message msg)重写该方法传回一个Message直接调用其中的参数

关于Looper和MessageQueue:

使用消息机制并不需要手动创建Looper和MessageQueue,Looper的构造函数是私有的,而在其中调用了MessageQueue的构造方法。主线程在创建过程中,系统会自动为其添加Looper与Message Queue,子线程默认不会添加Looper与Message Queue,在子线程中使用Handler就必须先获取子线程的Looper(同时也就获取了MessageQueue),并在Handler代码结束后启动Looper。

总结:

关于项目

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

1) 系统机制

2) 自定义控件

3) 定制其他开源项目

4) Json某个字段值的类型可变

心态:

什么样的面试官都有,去面试的时候要做好一切心理准备,不管是技术还是基础都得扎实。一个人的交谈能力也很重要,总之不是非常标准的普通话, 最起码你说的得让别人听得懂,而且得把面试官讲得非常彻底,这样你获得offer的机会更大,谈工资也有优势~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: