andorid开发也做了3年有余了,也面试很多加企业,借此机会分享一下,我们中遇到过的问题以及解决方案吧,希望能够对正在找工作的andoird程序员有一定的帮助。
特别献上整理过的50道面试题目
1.listView的优化方式
重用convertView |
viewHolder |
static class viewHolder |
在列表里面有图片的情况下,监听滑动不加载图片 |
多个不同布局,可以创建不同的viewHolder和convertView进行重用 |
2.listView展示数据几种形式
从sqlite拉取数据源显示 |
从xml使用pull解析拉取数据源显示 |
从网络上拉取数据源显示 |
3.ipc
进程间通信主要包括管道, 系统IPC(Inter-Process Communication,进程间通信)(包括消息队列,信号,共享存储), 套接字(SOCKET). 目的: l 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。 l 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。 l 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。 l 资源共享:多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制。 l 进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。 进程通过与内核及其它进程之间的互相通信来协调它们的行为。Linux支持多种进程间通信(IPC)机制,信号和管道是其中的两种。除此之外,Linux还支持System V 的IPC机制(用首次出现的Unix版本命名)。 |
4.Parcel的机制
Android中的Parcel机制 实现了Bundle传递对象 使用Bundle传递对象,首先要将其序列化,但是,在Android中要使用这种传递对象的方式需要用到Android Parcel机制,即,Android实现的轻量级的高效的对象序列化和反序列化机制。 JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。 代码: 实体类:
|
5.JNI调用
(1) Eclipse中新建android工程 工程名 JNItest Package名com.ura.test Activity名 JNItest 应用程序名 JNItest (2) 编辑main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/JNITest" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/JNITest" /> </LinearLayout> (3)编辑java文件 package com.ura.test; import android.app.Activity; #ifndef _Included_com_ura_test_JNITest #ifdef __cplusplus #define LOG_TAG "JNITest" JNIEXPORT jstring JNICALL Java_com_ura_test_JNITest_GetTest } |
6.细谈四大组件
activity
1.什么是activity?
四大组件之一,一般的,一个用户交互界面对应一个activity setContentView() ,// 要显示的布局 button.setOnclickLinstener{ } , activity 是Context的子类,同时实现了window.callback和keyevent.callback, 可以处理与窗体用户交互的事件. 里面不能进行耗时操作 我开发常用的的有ListActivity , PreferenceActivity ,TabAcitivty等… 如果界面有共同的特点或者功能的时候,还会自己定义一个BaseActivity. |
2.activity生命周期?
Activity生命周期 1 完整生命周期 onCreate() --> onStart() --> onResume() 可以在手机上看见activity ---> onPause() --> onStop() 看不见了 ---> onDestory() 销毁了 2 前台生命周期 |
3.横竖屏切换时候activity的生命周期?
这个生命周期跟清单文件里的配置有关系 1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期 默认首先销毁当前activity,然后重新加载 2、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法 游戏开发中, 屏幕的朝向都是写死的. |
4.如何将一个activity设置成窗口的样式?
可以自定义一个activity的样式,详细见手机卫士的程序详细信息 android:theme="@style/FloatActivity" E:\day9\mobilesafe\res\values\style |
5.activity启动模式?
|
6.后台activity被系统回收了怎么办?如果后台activity由于某种原因被系统回收了,如何保存之前状态?
除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大. protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putLong("id", 1234567890); } public void onCreate(Bundle savedInstanceState) { //判断savedInstanceState是不是空. //如果不为空就取出来 super.onCreate(savedInstanceState); } |
7.如何退出activity,如何安全退出已调用多个activity的application?
退出activity 直接调用 finish () 方法 . //用户点击back键 就是退出一个activity 退出activity 会执行 onDestroy()方法 . 1、抛异常强制退出: 该方法通过抛异常,使程序Force Close。 验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。 //安全结束进程 android.os.Process.killProcess(android.os.Process.myPid()); 2、记录打开的Activity: 每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。 List<Activity> lists ; 在application 全集的环境里面 lists = new ArrayList<Activity>(); lists.add(activity); for(Activity activity: lists) { activity.finish(); } 3、发送特定广播: 在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。 //给某个activity 注册接受接受广播的意图 registerReceiver(receiver, filter) //如果过接受到的是 关闭activity的广播 就调用finish()方法 把当前的activity finish()掉 4、递归退出 在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。 上面是网上的一些做法. 其实 可以通过 intent的flag 来实现.. intent.setFlag(FLAG_ACTIVITY_CLEAR_TOP)激活一个新的activity,然后在新的activity的oncreate方法里面 finish掉. |
8.两activity之间怎么传递数据?
基本数据类型可以通过. Intent 传递数据 在A activity中 Intent intent = new Intent(); intent.putExtra(name, value) Bundle bundle = new Bundle(); bundle.putBoolean(key,value); intent.putExtras(bundle); extras.putDouble(key, value) // 通过intent putExtra 方法 基本数据类型 都传递 Intent i = getIntent(); i.getExtras(); intent.getStringExtra("key","value"); intent.getBooleanExtra("key","value") Bundle bundle = new Bundle(); bumdle.putShort(key, value); intent.putExtras(bumdle); intent.putExtras(bundle) -------------- Application 全局里面存放 对象 ,自己去实现自己的application的这个类, 基础系统的application , 每个activity都可以取到 ----------------- 让对象实现 implements Serializable 接口把对象存放到文件上. 让类实现Serializable 接口,然后可以通过ObjectOutputStream //对象输出流 File file = new File("c:\1.obj"); FileOutputStream fos = new FileOutputStream(file); ObjectOutputStream oos = new ObjectOutputStream(fos); Student stu = new Student(); oos.writeObject(stu); //从文件中把对象读出来 ObjectInputStream ois = new ObjectInputStream(arg0); Student stu1 = (Student) ois.readObject(); 文件/网络 intent.setData(Uri) Uri.fromFile(); //大图片的传递 |
9.讲一讲对activity的理解?
把上面的几点用自己的心得写出来 |
service
1.什么是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的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的话会抛出异常。 |
2.service是否在main thread中执行, service里面是否能执行耗时的操作?
默认情况,如果没有显示的指定service所运行的进程, Service和activity是运行在当前app所在进程的main thread(UI主线程)里面 service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 ) 在子线程中执行 new Thread(){}.start(); 特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让service在另外的进程中执行 |
3.怎么让在启动一个Activity是就启动一个service?
在activity的onCreate()方法里面 startService(); |
4.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 } } |
5.不用service,B页面为音乐播放,从A跳转到B,再返回,如何使音乐继续播放?
这个问题问的很山寨.默认不做任何处理,B里面的音乐都能播放. 遇到问题, 可以随机应变,灵活发挥,多考虑些细节,比如说这个题就可以这样说,说说你对startActivityForResult的理解() B的结束的时候 setResult() A会调用到onActivityResult() 就会获取到resultCode A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐. seekTo(resultCode) |
6.什么是IntentService?有何优点?
普通的service ,默认运行在ui main 主线程 Sdk给我们提供的方便的,带有异步处理的service类, 可以在OnHandleIntent() 处理耗时的操作 |
7.什么时候使用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可以使用startForeg round(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。 如果有其他的应用组件作为Service,Activity等运行在相同的进程中,那么将会增加该进程的重要性。 1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作. new Thread(){ TimerTask // 循环的执行一个定时的任务 }.start(); 2.Broadcast receiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作. ANR new Service() 3.远程的service如果被启动起来,可以被多次bind, 但不会重新create. 索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用. 画廊 摄像机 照相机 bindService() Ibinder的对象, 访问service |
8.如何在让Service杀不死?
Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,然后在onStartCommand方法中做一些处理。 从Android官方文档中,我们知道onStartCommand有4种int返回值,首先简单地讲讲int返回值的作用。 一、onStartCommand有4种返回值: START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。 START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。 START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。 START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。 二、创建不被杀死的service 1.在service中重写下面的方法,这个方法有三个返回值, START_STICKY(或START_STICKY_COMPATIBILITY)是service被kill掉后自动重写创建 @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY_COMPATIBILITY; //return super.onStartCommand(intent, flags, startId); } 或 @Override public int onStartCommand(Intent intent, int flags, int startId) { flags = START_STICKY; return super.onStartCommand(intent, flags, startId); // return START_REDELIVER_INTENT; } @Override public void onStart(Intent intent, int startId) { // 再次动态注册广播 IntentFilter localIntentFilter = new IntentFilter("android.intent.action.USER_PRESENT"); localIntentFilter.setPriority(Integer.MAX_VALUE);// 整形最大值 myReceiver searchReceiver = new myReceiver(); registerReceiver(searchReceiver, localIntentFilter); super.onStart(intent, startId); } 2.在Service的onDestroy()中重启Service. public void onDestroy() { Intent localIntent = new Intent(); localIntent.setClass(this, MyService.class); // 销毁时重新启动Service this.startService(localIntent); } 3.创建一个广播 public class myReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { context.startService(new Intent(context, Google.class)); } } 4.AndroidManifest.xml中注册广播myReceiver及MyService服务 <receiver android:name=".myReceiver" > <intent-filter android:priority="2147483647" ><!--优先级加最高--> <!-- 系统启动完成后会调用 --> <action android:name="android.intent.action.BOOT_COMPLETED" /> <!-- 解锁完成后会调用 --> <action android:name="android.intent.action.USER_PRESENT" /> <!-- 监听情景切换 --> <action android:name="android.media.RINGER_MODE_CHANGED" /> </intent-filter> </receiver> <service android:name=".MyService" > 注:解锁,启动,切换场景激活广播需加权限,如启动完成,及手机机状态等。 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 亲测ZTE U795手机Android 4.0.4版本adb push到system\app下android:persistent="true" 变成核心程序,在360杀掉进程的时候,myReceiver照样有效,保证service重生。呃 KILL问题: 1. settings 中stop service onDestroy方法中,调用startService进行Service的重启。 2.settings中force stop 应用 捕捉系统进行广播(action为android.intent.action.PACKAGE_RESTARTED) 3. 借助第三方应用kill掉running task 提升service的优先级,程序签名,或adb push到system\app下等 相较于/data/app下的应用,放在/system/app下的应用享受更多的特权,比如若在其Manifest.xml文件中设置persistent属性为true,则可使其免受out-of-memory killer的影响。如应用程序'Phone'的AndroidManifest.xml文件: <application android:name="PhoneApp" android:persistent="true" android:label="@string/dialerIconLabel" android:icon="@drawable/ic_launcher_phone"> ... </application> 设置后app提升为系统核心级别 |
Broadcast Receiver
1.什么是Broadcast Receiver
下面是Android Doc中关于BroadcastReceiver的概述:①广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。 ②应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。 ③广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。 有很多广播接收者 ,系统已经实现了. |
2.什么时候使用Broadcast Receiver
用于接收系统的广播通知, 系统会有很多sd卡挂载,手机重启,广播通知,低电量,来电,来短信等…. |
3.如何使用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) |
ContentProvider
1.什么是ContentProvider
|
2.什么时候使用ContentProvider
需要访问别人的数据的时候 |
3.如何使用ContentProvider
1.先是提供的数据类型等数据的类。package org.juetion.cp;
import android.net.Uri; /** public static final String AUTHORIY = "org.juetion.cp.MyContentProvider"; /** import android.content.ContentProvider; import org.juetion.sqlite3.DatabaseHelper; import java.util.HashMap; /** /** /** @Override @Override /** @Override @Override @Override 以下代码是在第一个APP里面的。 例如在第一个APP的Activity调用数据的查询: |
4.请介绍下ContentProvider是如何实现数据共享的。
ContentProvider 可以屏蔽数据操作的细节 文件 xml MyContentProvider 可以在不同应用程序之间共享数据 sharedpreference db 把自己的数据通过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[]) 联系人的信息 sms的内容content://sms/ } |
安全共同点
android安全学习 签名作用 1.sharedUserId 一样并且签名一次 可以实现数据共享 2.升级应用 权限:细粒度的特权管理 权限与操作关联 应用需要显式申请权限 用户对权限可知(不可控) 对特权权限单独控制 四大组件 exported = true 等于public exported = false 等于private 默认组件private 如果该组件设置了intent-filter默认是public 如果同时希望是private,就需要主动设置expoted=false Securing Activities 可知指定权限才能启动activity service同上 BoradcastReceiver可以设置接发的权限 ContentPrivider 可设置读写Permission |
7.多线程管理
本篇随笔将讲解一下Android的多线程的知识,以及如何通过AsyncTask机制来实现线程之间的通信。 一、Android当中的多线程 在Android当中,当一个应用程序的组件启动的时候,并且没有其他的应用程序组件在运行时,Android系统就会为该应用程序组件开辟一个新的线程来执行。默认的情况下,在一个相同Android应用程序当中,其里面的组件都是运行在同一个线程里面的,这个线程我们称之为Main线程。当我们通过某个组件来启动另一个组件的时候,这个时候默认都是在同一个线程当中完成的。当然,我们可以自己来管理我们的Android应用的线程,我们可以根据我们自己的需要来给应用程序创建额外的线程。 二、Main Thread 和 Worker Thread 在Android当中,通常将线程分为两种,一种叫做Main Thread,除了Main Thread之外的线程都可称为Worker Thread。 当一个应用程序运行的时候,Android操作系统就会给该应用程序启动一个线程,这个线程就是我们的Main Thread,这个线程非常的重要,它主要用来加载我们的UI界面,完成系统和我们用户之间的交互,并将交互后的结果又展示给我们用户,所以Main Thread又被称为UI Thread。 Android系统默认不会给我们的应用程序组件创建一个额外的线程,所有的这些组件默认都是在同一个线程中运行。然而,某些时候当我们的应用程序需要完成一个耗时的操作的时候,例如访问网络或者是对数据库进行查询时,此时我们的UI Thread就会被阻塞。例如,当我们点击一个Button,然后希望其从网络中获取一些数据,如果此操作在UI Thread当中完成的话,当我们点击Button的时候,UI线程就会处于阻塞的状态,此时,我们的系统不会调度任何其它的事件,更糟糕的是,当我们的整个现场如果阻塞时间超过5秒钟(官方是这样说的),这个时候就会出现 ANR (Application Not Responding)的现象,此时,应用程序会弹出一个框,让用户选择是否退出该程序。对于Android开发来说,出现ANR的现象是绝对不能被允许的。 另外,由于我们的Android UI控件是线程不安全的,所以我们不能在UI Thread之外的线程当中对我们的UI控件进行操作。因此在Android的多线程编程当中,我们有两条非常重要的原则必须要遵守: 绝对不能在UI Thread当中进行耗时的操作,不能阻塞我们的UI Thread 不能在UI Thread之外的线程当中操纵我们的UI元素 三、如何处理UI Thread 和 Worker Thread之间的通信 既然在Android当中有两条重要的原则要遵守,那么我们可能就有疑问了?我们既不能在主线程当中处理耗时的操作,又不能在工作线程中来访问我们的UI控件,那么我们比如从网络中要下载一张图片,又怎么能将其更新到UI控件上呢?这就关系到了我们的主线程和工作线程之间的通信问题了。在Android当中,提供了两种方式来解决线程直接的通信问题,一种是通过Handler的机制(这种方式在后面的随笔中将详细介绍),还有一种就是今天要详细讲解的 AsyncTask 机制。 四、AsyncTask AsyncTask:异步任务,从字面上来说,就是在我们的UI主线程运行的时候,异步的完成一些操作。AsyncTask允许我们的执行一个异步的任务在后台。我们可以将耗时的操作放在异步任务当中来执行,并随时将任务执行的结果返回给我们的UI线程来更新我们的UI控件。通过AsyncTask我们可以轻松的解决多线程之间的通信问题。 怎么来理解AsyncTask呢?通俗一点来说,AsyncTask就相当于Android给我们提供了一个多线程编程的一个框架,其介于Thread和Handler之间,我们如果要定义一个AsyncTask,就需要定义一个类来继承AsyncTask这个抽象类,并实现其唯一的一个 doInBackgroud 抽象方法。要掌握AsyncTask,我们就必须要一个概念,总结起来就是: 3个泛型,4个步骤。 3个泛型指的是什么呢?我们来看看AsyncTask这个抽象类的定义,当我们定义一个类来继承AsyncTask这个类的时候,我们需要为其指定3个泛型参数: AsyncTask <Params, Progress, Result> Params: 这个泛型指定的是我们传递给异步任务执行时的参数的类型 Progress: 这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型 Result: 这个泛型指定的异步任务执行完后返回给UI线程的结果的类型 我们在定义一个类继承AsyncTask类的时候,必须要指定好这三个泛型的类型,如果都不指定的话,则都将其写成Void,例如: AsyncTask <Void, Void, Void> 4个步骤:当我们执行一个异步任务的时候,其需要按照下面的4个步骤分别执行 onPreExecute(): 这个方法是在执行异步任务之前的时候执行,并且是在UI Thread当中执行的,通常我们在这个方法里做一些UI控件的初始化的操作,例如弹出要给ProgressDialog doInBackground(Params... params): 在onPreExecute()方法执行完之后,会马上执行这个方法,这个方法就是来处理异步任务的方法,Android操作系统会在后台的线程池当中开启一个worker thread来执行我们的这个方法,所以这个方法是在worker thread当中执行的,这个方法执行完之后就可以将我们的执行结果发送给我们的最后一个 onPostExecute 方法,在这个方法里,我们可以从网络当中获取数据等一些耗时的操作 onProgressUpdate(Progess... values): 这个方法也是在UI Thread当中执行的,我们在异步任务执行的时候,有时候需要将执行的进度返回给我们的UI界面,例如下载一张网络图片,我们需要时刻显示其下载的进度,就可以使用这个方法来更新我们的进度。这个方法在调用之前,我们需要在 doInBackground 方法中调用一个 publishProgress(Progress) 的方法来将我们的进度时时刻刻传递给 onProgressUpdate 方法来更新 onPostExecute(Result... result): 当我们的异步任务执行完之后,就会将结果返回给这个方法,这个方法也是在UI Thread当中调用的,我们可以将返回的结果显示在UI控件上 为什么我们的AsyncTask抽象类只有一个 doInBackground 的抽象方法呢??原因是,我们如果要做一个异步任务,我们必须要为其开辟一个新的Thread,让其完成一些操作,而在完成这个异步任务时,我可能并不需要弹出要给ProgressDialog,我并不需要随时更新我的ProgressDialog的进度条,我也并不需要将结果更新给我们的UI界面,所以除了 doInBackground 方法之外的三个方法,都不是必须有的,因此我们必须要实现的方法是 doInBackground 方法。 五、通过AsyncTask来从网络上下载一张图片 下面我们就通过两个代码示例,来看看如何通过AsyncTask来从网络上下载一张图片,并更新到我们的ImageView控件上。 ①下载图片时,弹出一个ProgressDialog,但是不显示实时进度 我们来看看布局文件: <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" <ImageView <Button </RelativeLayout]] 就是很简单的一个ImageView控件和一个Button控件,当点击Button控件时,弹出一个ProgressDialog,然后开启一个异步任务,从网络中下载一张图片,并更新到我们的ImageView上。这里还要注意一点,如果我们要使用手机访问网络,必须还要给其授权才行,在后续的学习当中,将会详细讲解Android当中的授权的知识。我们来看看 <?xml version="1.0" encoding="utf-8"?><manifestxmlns:android="http://schemas.android.com/apk/res/android" <uses-sdk <activity <intent-filter]] <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </activity]] </application]] </manifest]] 接下来我们来看看我们的Activity代码: publicclass MainActivityextends Activity } 我们来看看效果图: publicclass MainActivityextends Activity } 我们来看看效果图: 这样我们就能够通过AsyncTask来实现从网络中下载一张图片,然后将其更新到UI控件中,并时时刻刻的更新当前的进度这个功能了。 |
8.android内存优化及管理
1、使用优化过的数据容器。 在Android framework下,建议使用优化过的数据容器比如:SparseArray,SparseBooleanArray,LongSparseArray。通用的HashMap实现的内存使用率非常的低,因为他需要为每一个mapping创建一个分离的entry object。另外,SparseArray类避免了系统对有些key的自动装箱,因而带来了更高的效率。 2、注意内存的开销。[size=12.800000190734863px] 注意你使用的语言和第三方库的成本和开销,要自始至终的将这些因素考虑在你的程序设计中。通常,有些事情表面上看着没什么问题但实际上的开销让人惊叹。比如: ·枚举相对于静态常量来说,需要两倍甚至更多的内存。你应该完全避免在Android中使用枚举。 [size=12.666666984558105px]·每一个在java中的类(包括匿名内部类)使用大约500 bytes的代码量。 ·每一个类的实例拥有12-16 bytes的RAM消耗。 ·放置一个单独的实体到HashMap中,一个额外加的实体对象分配需要花费32 bytes。 [size=12.666666984558105px]3、关于代码的抽象 抽象是一个好的编程的基础,因为抽象可以提高代码的灵活性和可维护性。然而抽象也带来了一定的花销,一般情况下,他们有更多的代码需要执行,需要更多的时间和更多RAM来将这些代码映射到内存中。因此,如果你的抽象不能带来巨大的好处,你就应该割掉你的赘肉。 4、避免依赖注入框架 虽然注入框架给我们带来了很多方便,但是在使用这些框架的时候,框架需要花费很多时间来扫描我们自己写的代码,甚至会将哪些你根本不需要的东西也加载到内存中。 5、小心的使用扩展库 很多扩展库的代码不是针对手机环境开发的,可能在用到移动客户端的时候会导致很低的效率。因此在使用之前,需要评估一下其占用内存的大小。 即使库针对手机开发,也会有潜在的危险,因为每一个Library做的事情不尽相同。比如,一个Library使用nano protobufs而另一个使用micro protobufs。现在,在你的app中就有两个protobuf。类似情况经常发生。 6、使用混淆器移除不必要的代码 ProGuard工具通过移除无用代码,使用语意模糊来保留类,字段和方法来压缩,优化和混淆代码。可以使你的代码更加完整,更少的RAM 映射页。 7、使用多个进程(注意是process 不是 thread ok?) 如果这适合你的app,可能帮助你管理你的app的内存就是将你的app多个部分分配到多个进程中。该技术必须小心使用并且大多数应用不应该运行在多个进程下。这个技术的主要应用是后台工作跟天台工作一样重要的情况下。典型应用就是:当音乐播放器从服务器下载并长时间播放音乐,一般将其分为两个进程:一个是UI,另一个位置后台服务的运行。 like this:
[size=12.666666984558105px]process后面需要记住要有个":",这表示该进程属于你的app。 一般情况下,一块基本的空进程需要的内存大小在1.4m左右。
8、基本性能优化方法的基本原则: 1)不要做你不必要的工作; 2)不要申请不必要的内存; 9、关于UI上的一些问题[size=12.800000190734863px] Hierarchy Viewer[size=12.666666984558105px] [size=12.666666984558105px]通过他,可以看到你自己的Layout文件存在的问题。你可以看到你的Layout每一部分计算,布局,渲染所需要的时间。尽量的使你的Layout扁平话,深度最好保持 在三层之内[size=12.666666984558105px] 。RelativeLayout[size=12.666666984558105px] 是解决使用LinearLayout堆叠多层问题的利剑。那些为了方便 使[size=12.666666984558105px] 用LinearLayout的layout_weight属性[size=12.666666984558105px] 的哥们,需要重点注意,这个属性真的可以减慢measure速度。所以在使用之前,一定要再三考虑,是否真的不能通过其他方法来完成你要的效果?
使用oc计数器的方式可以更好的控制内存 Android OnLowMemory和OnTrimMemory OnLowMemory |
9.图片缓存机制
目前很多商业应用都会涉及到从网络上读取图片数据的问题,为了节约用户流量,应用一般会将图片缓存起来。图片缓存一般分为内存缓存和外存缓存。内存缓存运用java的缓存机制,在程序完全退出后,缓存所在的内存空间可能被其它应用程序占用从而丢失。外存缓存一般放在程序特有的访问空间或者sd卡中,在sd卡中存放的资源为公有资源,其它程序也可以访问,且对用户来讲没有一个强制清除缓存的规范机制。综合以上,本文采用将缓存图片放置在程序的特有空间中, 其它应用程序无法访问,且用户可以在应用程序管理中的"清除数据"选项中清除缓存。 本文提供三种缓存策略:(1)LRU算法,固定缓存图片数量(max_num),当图片数量超出max_num时,将缓存中最近用的最少的图片删除。(2)FTU算法,固定每张图片的缓存时限,以最后一次使用算起,超过时限后删除。(3)FMU算法,在存储器中固定一定大小的存储空间,超过固定空间后将缓存中占用最大尺寸的图片删除。使用时只需要向方法体中传递图片的URL即可。 代码片段 使用方法: public class ImagecachetacticsdemoActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.item); /*FMU*/ imageCacheManager = ImageCacheManager.getImageCacheService(this, ImageCacheManager.MODE_FIXED_MEMORY_USED, "memory"); imageCacheManager.setMax_Memory(1024 * 1024); /*FTU*/ // imageCacheManager = ImageCacheManager.getImageCacheService(this, // ImageCacheManager.MODE_FIXED_TIMED_USED, "time"); // imageCacheManager.setDelay_millisecond(3 * 60 * 1000); /*LRU*/ // imageCacheManager = ImageCacheManager.getImageCacheService(this, // ImageCacheManager.MODE_LEAST_RECENTLY_USED, "num"); // imageCacheManager.setMax_num(5); // imageCacheManager = ImageCacheManager.getImageCacheService(this, // ImageCacheManager.MODE_NO_CACHE_USED, "nocache"); mImageView = (ImageView) findViewById(R.id.imageView); new DownloadTask() .execute("http://www.touxiang99.com/uploads/allimg/110417/1_110417112640_2.jpg"); } private class DownloadTask extends AsyncTask<String, Void, Bitmap> { @Override protected Bitmap doInBackground(String... params) { try { return imageCacheManager.downlaodImage(new URL(params[0])); } catch (IOException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Bitmap result) { mImageView.setImageBitmap(result); super.onPostExecute(result); } @Override protected void onPreExecute() { mImageView.setImageResource(R.drawable.ic_launcher); super.onPreExecute(); } } private ImageView mImageView; private ImageCacheManager imageCacheManager; |
10.Handler机制
11.什么是ANR 如何避免它?
ANR:Application NotResponding,五秒 在Android中,活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时,Android就会显示ANR对话框了: 对输入事件(如按键、触摸屏事件)的响应超过5秒 意向接受器(intentReceiver)超过10秒钟仍未执行完毕 Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着,任何在主线程中运行的,需要消耗大量时间的操作都会引发ANR。因为此时,你的应用程序已经没有机会去响应输入事件和意向广播(Intentbroadcast)。 因此,任何运行在主线程中的方法,都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作,如访问网络和数据库;或者是开销很大的计算,比如改变位图的大小,需要在一个单独的子线程中完成(或者是使用异步请求,如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 -- 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是,主线程为子线程提供一个句柄(Handler),让子线程在即将结束的时候调用它(xing:可以参看Snake的例子,这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序,能够保证你的程序对输入保持良好的响应,从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程,因为他们都面临着同样的超时问题。 |
12.sqlite操作使用
|
13请描述一下Intent 和 Intent Filter。
Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封Email,其中不仅应该包含收件地址,还可以包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。 通过Intent 可以实现各种系统组件的调用与激活. Intent filter: 可以理解为邮局或者是一个信笺的分拣系统… 这个分拣系统通过3个参数来识别 Action: 动作 view Data: 数据uri uri 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"); startActivity(intent); 那么所有的 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"/> Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); insent.setData( Uri.parse(tel:12345)); startAcitivty(); 电话的uri tel: 12345 http://www.baidu.com 自己定义的uri itcast://cn.itcast/person/10 如果在 Intent Filter 中指定了这些属性,那么只有所有的属性都匹配成功时 URI 数据匹配才会成功。 Category 类别匹配 <intent-filter >节点中可以为组件定义一个 Category 类别列表,当 Intent 中包含这个列表的所有项目时 Category 类别匹配才会成功。 默认是DEFAULT |
14.Intent传递数据时,可以传递哪些类型数据?
1.一般的基本数据类型 Intent .putextra() intent.getextra(); Parselable Serializable 2.数据的uri, intent.setData() intent.getData(); |
15.Android事件传递机制
Android中dispatchTouchEvent,onInterceptTouchEvent, onTouchEvent的理解ec android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。 一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE...->ACTION_MOVE->ACTION_UP android的事件处理分为3步。 1)public booleandispatchTouchEvent(MotionEvent ev) 这个方法用来分发TouchEvent 2)public boolean onInterceptTouchEvent(MotionEvent ev) 这个方法用来拦截TouchEvent 3)public boolean onTouchEvent(MotionEvent ev) 这个方法用来处理TouchEvent 假设当前Activity 布局如下: dispatchTouchEvent事件分发 事件拦截:onInterceptTouchEvent 当某个控件的onInterceptTouchEvent()返回值为true时,就会发生截断,事件被传到当前控件的onTouchEvent()。如我们将LayoutView2的onInterceptTouchEvent()返回值为true,则传递流程变成: 如果我们同时将LayoutView2的onInterceptTouchEvent()和onTouchEvent()设置成true,那么LayoutView2将消费被传递的事件,同时后续事件(如跟着ACTION_DOWN的ACTION_MOVE或者ACTION_UP)会直接传给LayoutView2的onTouchEvent(),不传给其他任何控件的任何函数。同时传递给子空间一个ACTION_CANCEL事件。传递流程变成(图中没有画出ACTION_CANCEL事件): 小总结:onInterceptTouchEvent是自rootiew向下传递, onTouchEvent正好相反。 |
16.请介绍下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" view android:layout_y="12px" fwvga 854*480apk qq斗地主 qq游戏大厅800*480 800*480.apk fwvga 854*480 指定平板机型的游戏开发中经常用到绝对布局 widget 绝对布局 指定机型的平板游戏开发. 2.3 3.0 1. 界面布局 任务管理器 gridview 2. 手机 任务管理 listview lephone lepad RelativeLayout 相对布局可以理解为某一个元素为参照物,来定位的布局方式。主要属性有: 相对于某一个元素 android:layout_below="@id/aaa" 该元素在 id为aaa的下面 android:layout_toLeftOf="@id/bbb" 改元素的左边是bbb 相对于父元素的地方 android:layout_alignParentLeft="true" 在父元素左对齐 android:layout_alignParentRight="true" 在父元素右对齐 Android oa客户端. TableLayout <table> 表格布局类似Html里面的Table。每一个TableLayout里面有表格行TableRow,TableRow里面可以具体定义每一个元素,设定他的对齐方式android:gravity="" 。 每一个布局都有自己适合的方式,另外,这五个布局元素可以相互嵌套应用,做出美观的界面。 oa 自动化 生成报表 ,图标 表示 webview css div webview |
17.谈谈UI中,Padding和Margin有什么区别?
Padding 文字对边框, margin是控件对父窗体. Padding 盒子里面的内容距离盒子的距离 , margin 盒子与盒子之间的距离 |
18.请解释下在单线程模型中Message、Handler、Message Queue、Looper之间的关系。
简单的说,Handler获取当前线程中的looper对象,looper用来从存放Message的MessageQueue中取出Message,再有Handler进行Message的分发和处理. |
19.AIDL的全称是什么?如何工作?
AIDL的英文全称是Android Interface Define Language当A进程要去调用B进程中的service时,并实现通信,我们通常都是通过AIDL来操作的A工程:首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件,在里面我们自定义一个接口,含有方法get。ADT插件会在gen目录下自动生成一个RemoteService.java文件,该类中含有一个名为RemoteService.stub的内部类,该内部类中含有aidl文件接口的get方法。说明一:aidl文件的位置不固定,可以任意然后定义自己的MyService类,在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类,实现get方法。在onBind方法中返回这个内部类的对象,系统会自动将这个对象封装成IBinder对象,传递给他的调用者。其次需要在AndroidManifest.xml文件中配置MyService类,代码如下:<!-- 注册服务 --> <service android:name=".MyService"> <intent-filter> <!-- 指定调用AIDL服务的ID --> <action android:name="net.blogjava.mobile.aidlservice.RemoteService" /> </intent-filter> </service>为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问,只要别的进程知道这个ID,正是有了这个ID,B工程才能找到A工程实现通信。说明:AIDL并不需要权限B工程: 首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中,在bindService方法中绑定aidl服务 绑定AIDL服务就是将RemoteService的ID作为intent的action参数。 说明:如果我们单独将RemoteService.aidl文件放在一个包里,那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起,那么我们在B工程中就要建立相应的包,以保证RmoteService.java文件的报名正确,我们不能修改RemoteService.java文件 bindService(new Inten("net.blogjava.mobile.aidlservice.RemoteService"), serviceConnection, Context.BIND_AUTO_CREATE); ServiceConnection的onServiceConnected(ComponentName name, IBinder service)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。 |
20.请解释下Android程序运行时权限与文件系统权限的区别。
Android程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 打电话,访问网络,获取坐标,读写sd卡,读写联系人等..安装的时候会提示用户… 文件系统的权限是linux权限. 比如说sharedpreference里面的Context.Mode.private Context.Mode.world_read_able Context.Mode_world_writeable 777自己 同组 其他 |
21.系统上安装了多种浏览器,能否指定某浏览器访问指定页面
Intent intent =newIntent(); intent.setAction("android.intent.action.VIEW"); Uri content_url =Uri.parse("http://www.163.com"); intent.setData(content_url); intent.setClassName("com.android.browser","com.android.browser.BrowserActivity"); startActivity(intent); 只要修改以intent.setClassName("com.android.browser","com.android.browser.BrowserActivity"); 中相应的应用程序packagename 和要启动的activity即可启动其他浏览器来 uc浏览器":"com.uc.browser", "com.uc.browser.ActivityUpdate“ opera浏览器:"com.opera.mini.android", "com.opera.mini.android.Browser" qq浏览器:"com.tencent.mtt", "com.tencent.mtt.MainActivity" |
22.对android主线程的运用和理解。
主ui线程不能执行耗时的操作 |
23.对android虚拟机的理解,包括内存管理机制垃圾回收机制。dalvik和art区别
虚拟机很小,空间很小,谈谈移动设备的虚拟机的大小限制 16M , 谈谈加载图片的时候怎么处理大图片的, outmemoryException BitmapFactory.option 垃圾回收,没有引用的对象,在某个时刻会被系统gc掉 . Dalvik和标准Java虚拟机(JVM)首要差别 许多GC实现都是在对象开头的地方留一小块空间给GC标记用。Dalvik VM则不同,在进行GC的时候会单独申请一块空间,以位图的形式来保存整个堆上的对象的标记,在GC结束后就释放该空间。 |
24.Framework工作方式及原理,Activity是如何生成一个view的,机制是什么。
主要用到反射和代理的知识。主要用pull解析xml,然后通过反射得到属性,在onDrew画出来 反射 , 配置文件 可以讲下activity的源码,比如说 每个activity里面都有window.callback和keyevent.callback,一些回调的接口或者函数吧. 框架把activity创建出来就会调用里面的这些回调方法,会调用activity生命周期相关的方法. Activity创建一个view是通过ondraw 画出来的, 画这个view之前呢,还会调用onmeasure方法来计算显示的大小. |
25.android本身的一些限制,比如apk包大小限制,读取大文件时的时间限
这个问题问的有问题, apk包大小限制不好说, *飞车有100M 还是能装到手机上, 世面google market 上大程序 主程序 很小 5~10M 下载sdcard 200~300M 15分钟之内 申请退款 apk包,精简包, 素材存放在服务器. 游戏程序. 读大文件的时间限制应该是main线程里面的时间限制吧.5秒. |
26.Android程序与Java程序的区别?
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 将Java 游戏或者j2me程序移植到Android平台的过程中, Android SDK 与Java SDK的区别是很需要注意的地方。 sampleDataAdpter("YY-MM-DD") |
27.Android中Task任务栈的分配
首先我们来看下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模型,足以应付,但是,涉及到实际的性能、开销等问题,就会变得残酷许多。 |
28.在Android中,怎么节省内存的使用,怎么主动回收内存?
回收已经使用的资源, 合理的使用缓存 合理设置变量的作用范围… application 对象 //未来的某一段时间执行 System.gc(); |
29.不同工程中的方法是否可以相互调用?
可以,列举aidl访问远程服务的例子. |
30.dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念 是同一概念
Dvm的进程是dalivk虚拟机进程,每个android程序都运行在自己的进程里面, 每个android程序系统都会给他分配一个单独的liunx uid(user id), 每个dvm都是linux里面的一个进程.所以说这两个进程是一个进程. |
31.在Android中是如何实现判断区分电话的状态,去电,来电、未接来电?
Day8 showAddressService.java TelephoneyManger.listen(); |
32.谈谈Android的优点和不足之处。
1、开放性,开源ophone 阿里云( 完全兼容android) 2、挣脱运营商束缚 3、丰富的硬件选择 mtk android 4、不受任何限制的开发商 5、无缝结合的Google应用 缺点也有5处: 1、安全问题、隐私问题 2、卖手机的不是最大运营商 3、运营商对Android手机仍然有影响 4、山寨化严重 5、过分依赖开发商,缺乏标准配置 |
33.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 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用 |
34.Android UI中的View如何刷新。
在主线程中 拿到view调用Invalide()方法,查看画画板里面更新imageview的方法 在子线程里面可以通过postInvalide()方法; |
35. 简单描述下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只是在应用程序安装的时候才会检查证书的有效期。如果程序已经安装在系统中,即使证书过期也不会影响程序的正常功能。 |
36.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动画,传统的动画方法,通过顺序的播放排列好的图片来实现,类似电影。 |
37.说说mvc模式的原理,它在android中的运用
Android中没有mvc,只有在j2ee中有,是用于逻辑也界面分离的 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中显示。 |
38.通过点击一个网页上的url 就可以完成程序的自动安装,描述下原理
Day11 AddJavascriptInterface new Object{ callphone(); installapk(); } 将js与java相互调用再来一个例子,解决相互调用之间的关系。 首先说明一重要代码的情况: android中的关键代码: js或html中调用android中方法代码: 下面给出具体的测试代码: [java] view plaincopyprint? [javascript] view plaincopyprint? 1、把方向键的流程改成:先传给webcore,假如没处理,再在webview里面处理,这个需要修改webview.java代码 测试结果如下: 点击buttons按钮: you press KEY_RIGHT you press KEY_UP you press KEY_DOWN you press KEY_LEFT 这里为何使用这种方式,是因为对于上下左右及确定这种功能键被webview截取掉了,无法传递到webcore中,而只能重载OnKeyDown/OnKeyUp方法,再由js调用java方法来获取得。 [javascript] view plaincopyprint? |
39.Service和Activity在同一个线程吗
默认情况同一线程 main主线程 ui线程 |
40.ViewStub的应用
在开发应用程序的时候,经常会遇到这样的情况,会在运行时动态根据条件来决定显示哪个View或某个布局。那么最通常的想法就是把可能用到的View都写在上面,先把它们的可见性都设为View.GONE,然后在代码中动态的更改它的可见性。这样的做法的优点是逻辑简单而且控制起来比较灵活。但是它的缺点就是,耗费资源。虽然把View的初始可见View.GONE但是在Inflate布局的时候View仍然会被Inflate,也就是说仍然会创建对象,会被实例化,会被设置属性。也就是说,会耗费内存等资源。 推荐的做法是使用android.view.ViewStub,ViewStub是一个轻量级的View,它一个看不见的,不占布局位置,占用资源非常小的控件。可以为ViewStub指定一个布局,在Inflate布局的时候,只有ViewStub会被初始化,然后当ViewStub被设置为可见的时候,或是调用了ViewStub.inflate()的时候,ViewStub所向的布局就会被Inflate和实例化,然后ViewStub的布局属性都会传给它所指向的布局。这样,就可以使用ViewStub来方便的在运行时,要还是不要显示某个布局。 但ViewStub也不是万能的,下面总结下ViewStub能做的事儿和什么时候该用ViewStub,什么时候该用可见性的控制。 首先来说说ViewStub的一些特点: 1. ViewStub只能Inflate一次,之后ViewStub对象会被置为空。按句话说,某个被ViewStub指定的布局被Inflate后,就不会够再通过ViewStub来控制它了。 2. ViewStub只能用来Inflate一个布局文件,而不是某个具体的View,当然也可以把View写在某个布局文件中。 基于以上的特点,那么可以考虑使用ViewStub的情况有: 1. 在程序的运行期间,某个布局在Inflate后,就不会有变化,除非重新启动。 因为ViewStub只能Inflate一次,之后会被置空,所以无法指望后面接着使用ViewStub来控制布局。所以当需要在运行时不止一次的显示和隐藏某个布局,那么ViewStub是做不到的。这时就只能使用View的可见性来控制了。 2. 想要控制显示与隐藏的是一个布局文件,而非某个View。 因为设置给ViewStub的只能是某个布局文件的Id,所以无法让它来控制某个View。 所以,如果想要控制某个View(如Button或TextView)的显示与隐藏,或者想要在运行时不断的显示与隐藏某个布局或View,只能使用View的可见性来控制。 下面来看一个实例 在这个例子中,要显示二种不同的布局,一个是用TextView显示一段文字,另一个则是用ImageView显示一个图片。这二个是在onCreate()时决定是显示哪一个,这里就是应用ViewStub的最佳地点。 先来看看布局,一个是主布局,里面只定义二个ViewStub,一个用来控制TextView一个用来控制ImageView,另外就是一个是为显示文字的做的TextView布局,一个是为ImageView而做的布局: [html] view plaincopyprint? [html] view plaincopyprint? [html] view plaincopyprint? [java] view plaincopyprint? 使用的时候的注意事项: |
41.android开发中怎么去调试bug
逻辑错误 1.断点 debug 2. logcat , 界面布局,显示 hierarchyviewer.bat |
42.书写出android工程的目录结构以及相关作用
下面是HelloAndroid项目在eclipse中的目录层次结构:
由上图可以看出项目的根目录下共有九个文件(夹),下面就这九个文件(夹)进行详解: |
43.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秒 |
44.谈谈NDK
NDK全称:Native Development Kit。 1、NDK是一系列工具的集合。 * NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的。[1] * NDK集成了交叉编译器,并提供了相应的mk文件隔离平台、CPU、API等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。 * NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。 2、NDK提供了一份稳定、功能有限的API头文件声明。 Google明确声明该API是稳定的,在后续所有版本中都稳定支持当前发布的API。从该版本的NDK中看出,这些API支持的功能非常有限,包含有:C标准库(libc)、标准数学库(libm)、压缩库(libz)、Log库(liblog)。 |
45.请介绍下Android的数据存储方式。
一.SharedPreferences方式 二sdcard 三内部存储 四SqliteDatabase 五. 网络存储方式 |
46.谈谈推送,优缺点以及实现原理
本文主旨在于,对目前Android平台上最主流的几种消息推送方案进行分析和对比,比较客观地反映出这些推送方案的优缺点,帮助大家选择最合适的实施方案。
方案1、使用GCM服务(Google Cloud Messaging) 方案2、使用XMPP协议(Openfire + Spark + Smack) 方案3、使用MQTT协议(更多信息见:http://mqtt.org/) 方案4、使用HTTP轮循方式 对各个方案的优缺点的研究和对比,推荐使用MQTT协议的方案进行实现,主要原因是:MQTT最快速,也最省流量(固定头长度仅为2字节),且极易扩展,适合二次开发。接下来,我们就来分析使用MQTT方案进行Android消息的原理和方法,并架设自己的推送服务。 实际上,其他推送系统(包括GCM、XMPP方案)的原理都与此类似。 2、推送服务端准备 a> 下载&解压rsmb安装包(下载地址:http://www.alphaworks.ibm.com/tech/rsmb) [html] view plaincopy 3、推送客户端准备 a> 下载&解压AndroidPushNotificationsDemo项目(下载地址:https://github.com/tokudu/AndroidPushNotificationsDemo) 注意:在新版本的Android SDK中可能会遇到以下错误。 运行效果如下: 点击“Start Push Service”按钮即可开启推送服务。这时我们可以看到rsmb的服务日志中打出以下提示: 4、发送服务准备 a> 下载&解压PHP版的发送服务端代码send_mqtt.zip(下载地址:http://download.csdn.net/detail/shagoo/4520102) |
47.谈谈数据加密
数据加密又称密码学,它是一门历史悠久的技术,指通过加密算法和加密密钥将明文转变为密文,而解密则是通过解密算法和解密密钥将密文恢复为明文。数据加密目前仍是计算机系统对信息进行保护的一种最可靠的办法。它利用密码技术对信息进行加密,实现信息隐蔽,从而起到保护信息的安全的作用。用自己的话来说就是,只有双方才知道的协议。 数据加密 - 密码算法分类 1按发展进程分密码的发展:古典密码,对称密钥 密码公开密钥密码. 2按加密模式分对称算法:序列密码和分组密码. 经典密码 代替密码: 简单代替多名或同音代替多表代替多字母或多码代替换位密码: •对称加密算法 DES AES •非对称公钥算法 RSA 背包密码McEliece密码Rabin 椭圆曲线EIGamal D_H |
48.解决问题和思考问题的方式
首先查看官方提供的API,通过自己对功能的理解,然后通过网络的途径,下载demo可以选择 github ,查找问题可以选择 stackover flow,然后可以问身边的朋友。 |
49.列举7到12个设计模式 以及它们的应用场景
设计模式,提供了很多软件工程问题所需处理的解决方案。 根据模式的目的可分为3类: 1.创建型模式:与对象的创建有关。 2.结构性模式:处理类与对象的组合。 3.行为性模式:对类或对象怎样交互和怎样 分配职责进行描述。 面向对象设计的2个基本原则: 1.针对接口编程,而不是针对实现编程。 2.优先使用对象组合,而不是类继承。 面向对象设计的5个设计原则: 1.单一职责原则(SRP) 2.开放封闭原则(OCP) 3.Liskov替换原则(LSP) 4.依赖倒置原则(DIP) 5.接口隔离原则(ISP) 23中设计模式: 1.创建型模式: (1).工厂方法模式 (2).抽象工厂模式 (3).创建者模式 (4).原型模式 (5).单例模式 2.结构型模式: (6).适配器模式 (7).桥模式 (8).组合模式 (9).装饰模式 (10).外观模式 (11).享元模式 (12).代理模式 3.行为型模式 (13).解释器模式 (14).模板方法模式 (15).职责链模式 (16).命令模式 (17).迭代器模式 (18).中介者模式 (19).备忘录模式 (20).观察者模式 (21).状态模式 (22).策略模式 (23).访问者模式 除此之外,后来人发现很多新的模式,如空模式等。 下面列举几个常见的问题导致重新设计,可能需要设计模式来分析解决: 1.通过显示的指定一个类来创建对象 2.对特殊操作的依赖 3.对硬件和软件平台的依赖 4.对对象表示或实现的依赖 5.算法依赖 6.紧耦合 7.通过生产子类来扩展功能 8.不能方便的对类进行修改 软件的设计臭味: 1.僵化性 2.脆弱性 3.顽固性 4.粘滞性 5.不必要的复杂性 6.不必要的重复 7.晦涩性 ... ... 总而言之,一句话,面向对象特性+原则+模式,折腾来折腾去就是这么个回事。 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。本章系Java之美[从菜鸟到高手演变]系列之设计模式,我们会以理论与实践相结合的方式来进行本章的学习,希望广大程序爱好者,学好设计模式,做一个优秀的软件工程师! 在阅读过程中有任何问题,请及时联系:egg。 邮箱:xtfggef@gmail.com 微博:http://weibo.com/xtfggef 如有转载,请说明出处:http://blog.csdn.net/zhangerqing 企业级项目实战(带源码)地址:http://zz563143188.iteye.com/blog/1825168 23种模式java实现源码及收集五年的开发资料下载地址: http://pan.baidu.com/share/home?uk=4076915866&view=share 一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下: 二、设计模式的六大原则 举例如下:(我们举一个发送邮件和短信的例子) 将上面的代码做下修改,改动下SendFactory类就行,如下: 请看例子: 适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。首先,我们来看看类的适配器模式,先看类图: 核心思想就是:有一个Source类,拥有一个方法,待适配,目标接口时Targetable,通过Adapter类,将Source的功能扩展到Targetable里,看代码: 只需要修改Adapter类的源码即可: 这个很好理解,在实际开发中,我们也常会遇到这种接口中定义了太多的方法,以致于有时我们在一些实现类中并不是都需要。看代码: Source类是被装饰类,Decorator类是一个装饰类,可以为Source类动态的添加一些功能,代码如下: 我们先看下实现类: 实现代码: 11、组合模式(Composite) 直接来看代码: FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。一提到共享池,我们很容易联想到Java里面的JDBC连接池,想想每个连接的特点,我们不难总结出:适用于作共享的一些个对象,他们有一些共有的属性,就拿数据库连接池来说,url、driverClassName、username、password及dbname,这些属性对于每个连接来说都是一样的,所以就适合用享元模式来处理,建一个工厂类,将上述类似属性作为内部数据,其它的作为外部数据,在方法调用时,当做参数传进来,这样就节省了空间,减少了实例的数量。 看下数据库连接池的代码: 13、策略模式(strategy) 图中ICalculator提供同意的方法, AbstractCalculator是辅助类,提供辅助方法,接下来,依次实现下每个类: 就是在AbstractCalculator类中定义一个主方法calculate,calculate()调用spilt()等,Plus和Minus分别继承AbstractCalculator类,通过对AbstractCalculator的调用实现对子类的调用,看下面的例子: 我解释下这些类的作用:MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。我们看实现代码: Invoker是调用者(司令员),Receiver是被调用者(士兵),MyCommand是命令,实现了Command接口,持有接收对象,看实现代码: 本章讲讲第三类和第四类。 Original类是原始类,里面有需要保存的属性value及创建一个备忘录类,用来保存value值。Memento类是备忘录类,Storage类是存储备忘录的类,持有Memento类的实例,该模式很好理解。直接看源码: State类是个状态类,Context类可以实现切换,我们来看看代码: 来看看原码:一个Visitor类,存放要访问的对象, User类统一接口,User1和User2分别是不同的对象,二者之间有关联,如果不采用中介者模式,则需要二者相互持有引用,这样二者的耦合度很高,为了解耦,引入了Mediator类,提供统一接口,MyMediator为其实现类,里面持有User1和User2的实例,用来实现对User1和User2的控制。这样User1和User2两个对象相互独立,他们只需要保持好和Mediator之间的关系就行,剩下的全由MyMediator类来维护!基本实现: Context类是一个上下文环境类,Plus和Minus分别是用来计算的实现,代码如下: |
50.谈谈你对框架的理解,设计框架的时候你是怎么考虑的,重构项目的时候你都遵循什么原则。
1.框架不要为应用做过多的假设 关于框架为应用做过多的假设, 一个非常具体的现象就是, 框架越俎代庖, 把本来是应 用要做的事情揽过来自己做。 这是一种典型的吃力不讨好的做法。 框架越俎代庖, 也许会使 得某一个具体应用的开发变得简单, 却会给其它更多想使用该框架的应用增加了本没有必要 的束缚和负担。 2.使用接口,保证框架提供的所有重要实现都是可以被替换的 框架终究不是应用, 所以框架无法考虑所有应用的具体情况, 保证所有重要的组件的实 现都是可以被替换的, 这一点非常重要, 它使得应用可以根据当前的实际情况来替换掉框架 提供的部分组件的默认实现。 使用接口来定义框架中各个组件及组件间的联系, 将提高框架 的可复用性。 3.框架应当简洁、一致、且目标集中 框架应当简洁, 不要包含那些对框架目标来说无关紧要的东西, 保证框架中的每个组件 的存在都是为了支持框架目标的实现。包含过多无谓的元素(类、接口、枚举等) ,会使框 架变得难以理解, 尝试将这些对于框架核心目标不太重要的元素转移到类库中, 可以使得框 架更清晰、目标更集中。 4.提供一个常用的骨架,但是不要固定骨架的结构,使骨架也是可以组装的 比如说, 如果是针对某种业务处理的框架, 那么框架不应该只提供一套不可变更的业务 处理流程,而是应该将处理流程 “单步” 化,使得各个步骤是可以重新组装的,如此一来,应 用便可以根据实际情况来改变框架默认的处理流程。 这种框架的可定制化能力可以极大地提 高框架的可复用性。 5.不断地重构框架 如果说设计和实现一个高质量的框架有什么秘诀?答案只有一个,重构、不断地重构。 重构框架的实现代码、 甚至重构框架的设计。 重构的驱动力源于几个方面, 比如对要解决的 本质问题有了更清晰准备的认识,在使用框架的时候发现某些组件职责不明确、难以使用, 框架的层次结构不够清晰等。 |
51.LRU算法
假设 序列为 4 3 4 2 3 1 4 2 物理块有3个 则 首轮 4调入内存 4 次轮 3调入内存 3 4 之后 4调入内存 4 3 之后 2调入内存 2 4 3 之后 3调入内存 3 2 4 之后 1调入内存 1 3 2(因为最少使用的是4,所以丢弃4) 之后 4调入内存 4 1 3(原理同上) 最后 2调入内存 2 4 1 在指定内存中如果超过内存剔除最近最少用的。 |
51.自定义控件的生命周期
onFinishInflate() 当View中所有的子控件均被映射成xml后触发 onMeasure( int , int ) 确定所有子元素的大小 onLayout( boolean , int , int , int , int ) 当View分配所有的子元素的大小和位置时触发 onSizeChanged( int , int , int , int ) 当view的大小发生变化时触发 onDraw(Canvas) view渲染内容的细节 onKeyDown( int , KeyEvent) 有按键按下后触发 onKeyUp( int , KeyEvent) 有按键按下后弹起时触发 onTrackballEvent(MotionEvent) 轨迹球事件 onTouchEvent(MotionEvent) 触屏事件 onFocusChanged( boolean , int , Rect) 当View获取或失去焦点时触发 onWindowFocusChanged( boolean ) 当窗口包含的view获取或失去焦点时触发 onAttachedToWindow() 当view被附着到一个窗口时触发 onDetachedFromWindow() 当view离开附着的窗口时触发,Android123提示该方法和 onAttachedToWindow() 是相反的。 onWindowVisibilityChanged( int ) 当窗口中包含的可见的view发生变化时触发 |