安卓面试基础知识总结_第1页
安卓面试基础知识总结_第2页
安卓面试基础知识总结_第3页
安卓面试基础知识总结_第4页
安卓面试基础知识总结_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1 Activity1.1 Activity 的概念是An droid应用层开发的四大组件之一,主要负责和用户交互部分,有自己的生命周期,在其上可以布置按钮,文本框等各种控件,简单来说就是An droid的UI部分。1.2 Activity 与 View 的区别1)Activity是四大组件中唯一一个用来和用户进行交互的组件。可以说Activity 就是an droid的视图层。2)如果再细化,Activity相当于视图层中的控制层,是用来控制和管理View的,真正用来显示和处理事件的实际上是View。3)每个Activity内部都有一个 Window对象,Window对象包含了一个Decor

2、View(实际上就是 FrameLayout),我们通过 setContentView 给 Activity 设置显示的 View实际上都是加到了 DecorView中。1.3 Activity 生命周期1.3.1生命周期主干方法描述可被杀死下一个on Create()在Activity 第一次被创建的时候被调用。 这里是你做所有初始化设置的地方一创建 视图、绑疋数据至列表等。如果曾经有状态记录(参阅后述 Saving ActivityState。),则调用此方法时会传入一个包含着此 activity 以前状 态的包对象做为参数否on Start()on Start ()在Activity正要

3、变得为用户所见时被调用。数据刷新时候调用! !当Activity转向前台时接着调用on Resume()在Activity变为隐臧时接着知行onStop()否on Resum e()on Stop()on Resume()在Activity开始与用户进行交互之前被调用。此时Activity位于堆栈顶部,并接收用户否onPause()输入。ActivityrunActivity 开始运仃on Pasue()当系统将要启动另一个Activity时调用。此方法主要用来将未保存的变化进行持久 化,停止类似动画这样耗费CPU勺动作等。 这一切动作应该在短时间内完成,因为下一 个Activity必须等到此

4、方法返回后才会继续。是on Resum e()on Stop()当Activity重新回到前台会执行onResume()【弹出对话框】。当Activity 变为用户不可见时会执行 onStop()。on Stop()当Activity不再为用户可见时调用此方法。这可能发生在它被销毁或者另一个 Activity (可能是现存的或者是新的)回到 运行状态并覆盖了它。是on Resta rt()on Destr oy()如果Activity再次回到前台跟用户交互则执行 onRestart().如果关闭Activity 则执行onDestroy()on Destroy。在Activity 销毁前调用。

5、这是Activity接收的最后一个调用。这可能发生在Activity 结束(调用了它的 finish()方法)或因为系统需要空间所以临 时的销毁了此Activity的实例时。可以用isFinishing()方法来区分这两种情况。是已经完 蛋了,还调用 毛线! ! !1.3.2其他中转方法on Restart()在Activity停止后,在再次启动之前被调用。之后执行onStart().否 on Sta rt()Activity lurehedActivity shul down1.4 Activity 启动模式1.4.1四种启动模式sta ndard默认模式,可以不用写配置。在这个模式下,都会

6、默认 创建一个新的实例。因此,在这种模式下,可以有多个相 同的实例,也允许多个相同 Activity 叠加。sin gleTop可以有多个实例,但是不允许多个相同Activity 叠加。 即,如果Activity 在栈顶的时候,启动相同的 Activity , 不会创建新的实例,而会调用其 onNewIntent方法。sin gleTask只有一个实例。在同一个应用程序中启动它的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它 Activity destory 掉并调用它的onNewlntent方法。如果是在别的应用程序中启动它,则会新

7、建一个 task, 并在该task中启动这个Activity ,singleTask允许别的 Activity 与其在一个task中共存,也就是说,如果我在这 个singleTask 的实例中再打开新的 Activity ,这个新的 Activity 还是会在singleTask的实例的task中。sin gleI nsta nee只有一个实例,并且这个实例独立运行在一个task中, 这个task只有这个实例,不允许有别的 Activity 存在。1.4.2配置样例1.5 Activity 启动方法1)在一个 Activity中调用 startActivity() 方法。,不带请求码。中调用

8、startActivityForResult() 方法。直接启动Activity2)在一个 Activity 带请求码启动Activity1.6请求码与响应码请求码(RequestCode)在一个业务中可能在两个按钮被单击事件中打开同一个Activity ,但我们在onActivityResult事件中如何判断是哪个按钮打开了新的Activity ?请求码就是为解决这个冋题的,那么我们打开新的Activity时应该使用startActivityForResult( in te nt, 1);。其中的第二个参数就是请求码。结果码(ResultCode)在一个业务中可能要打开多个不同的Activi

9、ty,那关闭Activity 时在onActivityResult事件中我们如何知道关闭的是哪一个Activity 呢?结果码就是为解决这个问题的,那么我们打开新的 Activity时应该使用setResult(2,in te nt);或在 关 闭Activity前 调 用ActivityObj.setResult(2); 。其中的第一个参数就是结果 码。在onActivityResult事件中,通过判断resultCode更可知道是哪个Activity 被关闭了。2 BroadcastReceiver2.1概念BroadcastReceiver也就是“广播接收者”的意思,顾名思义,它就是用来

10、 接收来自系统和应用中的广播。2.2应用场景在An droid系统中,广播体现在方方面面:eg:1. 当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动 服务的功能;2. 当锁屏或者点亮屏幕时就会产生一条广播,接收这条广播就可以实现一 些暂停或者开启一些耗电进程的功能。3. 当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做 出提示和保存数据等操作;4. 当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量 低时告知用户及时保存进度;2.3注册2.3.1静态注册 概念静态注册是在AndroidManifest.xml文件中配置的2.3.2动态注册

11、 概念动态注册需要在代码中动态的指定广播地址并注册需要注意的事项RegisterReceiver 是 android.content.ContextWrapper类中的方法,Activity 和Service都继承了 ContextWrapper,所以可以直接调用。在实际应 用中,我们在 Activity 或 Service 中注册了一个 BroadcastReceiver ,当这个 Activity 或 Service 被销毁时如果没有解除注册,系统会报一个异常,提示我 们是否忘记解除注册了。 所以,需要在特定的地方执行解除注册操作: 生命周期 的 onDestr

12、oy() 。有部分广播接受者,涉及到用户的敏感内容,需要在权限文件中声明。如开 机完成的广播,用户电量变化的广播,用户网络状态发生改变的广播2.3.3 生命周期1. 广播接收者的生命 周期是非常短暂的, 在接 收到 广播 的时 候创 建, onReceive() 方法结束之后销毁2. 广播接收者中不要做一些耗时的工作, 否则会弹出 Application NoResponse 错误对话框3. 最好也不要在广播接收者中创建子线程做耗时的工作, 因为广播接收者被销 毁后进程就成为了空进程,很容易被系统杀掉4. 耗时的较长的工作最好放在服务中完成3 Service3.1 概念服务是看不到界面的 ,,

13、就是一个没有界面的 Activity, 并且长期在后台运行的一个组件 .。3.2 为什么用服务 ?进程优先级 , 回收时是从 51, 从低到高Foreground process 前台进程Visible process 可视进程Service process 服务进程Background process 后台进程Empty process 空进程回收的优先级 : 先回收空进程 , 一个一个回收的 , 当内存够用时 , 不再回 收空进程 . 如果空进程回收完毕后 , 内存还是不够用时 , 继续向上一个一个的 回收后台进程 . 依次类推 .当系统内存不够用时 , 需要回收服务进程时 , 当系统内存

14、又够用时 , 会重 新启动服务 . 当用户去手动的把服务关闭时 , 服务不会再重启了3.3 作用由于 ANR对 Activity 和 BroadcastReceiver 响应时间的限制(Activity 对 事件响应不超过5秒,BroadcastReceiver执行不超过10秒),使得在其中都不 适合执行较耗时操作, 这样像网络、 数据库、复杂计算这类耗时操作的执行就需 要一个组件来承担。 Service 作为 Android 四大组件之一,其功能之一就是耗时 操作的执行,主要功能如下:a. 执行需要长时间运行的操作, 这个操作不与用户进行交互, 如网络下载、 大文件 I/O 、复杂计算、监听

15、手机状态。b. 应用内或应用间数据通信, Android 每个应用程序都在自己的 dalvik 虚 拟机中运行, 一个应用是不允许访问其他应用的内存信息的, 为此 Android 引入 了 Content Provider 在不同应用间共享数据, BroadcastReceiver 广播信息给 不同应用程序,但 Content Provider 更多用于数据的共享, BroadcastReceiver 广播的信息会被所有应用接收较耗费系统资源, 对于两个应用间动态的进行交互 还需要通过 Service 来完成。3.4 启动方式3.4.1 直接启动Activity 开启完服务后就不管服务了 .

16、Activity 和服务没有关系 . startService开启的服务 , 只有 stopService 可以关闭3.4.2 绑定启动绑定服务 , 生命周期方法会执行 : onUnbind - onDestory 服务销毁了 .在 activity 中调用 service 中的方法 .步骤:调用 bindService 方法绑定服务1. 在Activity 中定义一个连接桥的内部类,会在bindService方法传递给 service.2. 在 service 服务中 onBind 方法中返回一个 IBinder 接口对象 .3. 在service类中定义一个IBinder的内部实现类,在o

17、nBind方法返回.4. 当 onBinder 方法返回完对象后 , activity 中连接桥里的 onServiceConnected 会被调用, 其中形参 IBinder service 就是 service 类中 onBind 返回的对象 .5. activity 得到了 service 中的内部类对象 , 点击按钮是调用内部类中的 forwardBuyTicket 方法, 此方法会转调服务中 buyTicket 方法 .3.5 生命周期Service 的生命周期 (适用于 2.1 及以上)1. 被 startService 的无论是否有任何活动绑定到该 Service ,都在后台运行

18、。onCreate( 若需要 ) - onStart(int id, Bundle args).多次startService ,则 onStart 调用多次, 但不会创建多个 Service 实例,只需要一 次 stop 。该 Service 一直后台运行,直到 stopService 或者自己的 stopSelf() 或者资源不足由平台结束。2. 被 bindService 的调用 bindService 绑定,连接建立服务一直运行。未被 startService 只是 BindService ,则 onCreate() 执行, onStart(int,Bund , le) 不被调用;这种情

19、 况下绑定被解除,平台就可以清除该 Service( 连接销毁后,会导致解除,解除 后就会销毁 ) 。3. 被启动又被绑定类似 startService 的生命周期, onCreate onStart 都会调用。4. 停止服务时stopService 时显式 onDestroy() 。或不再有绑定 ( 没有启动时 ) 时隐式调用。 有 bind 情况下 stopService() 不起作用。dCiT曰血也0s tarfio-d bySo- mcwQ片FonRetndOonOwBlFOyl)T4 ContentProvider4.1 Co nten tProvider数据库在An droid当中

20、是私有的,当然这些数据包括文件数据和数据库数 据以及一些其他类型的数据。不能将数据库设为WORLD_READAB每个数据库都只能创建它的包访问, 这意味着只有由创建数据库的进程可访问它。如果需要在进程间传递数据,则可以使用AIDL/Binder或创建一个ContentProvider,但是不能跨越进程 /包边界直接来使用数据库。一个Content Provider类实现了一组标准的方法接口,从而能够让其他的 应用保存或读取此Content Provider 的各种数据类型。也就是说,一个程序可以通过实现一个 Content Provider的抽象接口将自 己的数据暴露出去。外界根本看不到,也不

21、用看到这个应用暴露的数据在应用当中是如何存储 的,或者是用数据库存储还是用文件存储,还是通过网上获得,这些一切都不重要,重要的是外界可以通过这一套标准及统一的接口和程序里的数据打交道, 可以读取程序的数据,也可以删除程序的数据,当然,中间也会涉及一些权限 的问题。下边列举一些较常见的接口,这些 接口如下所示。query (Uri uri, Strin g projecti on, String select ion, Strin gselectionArgs,String sortOrder ):通过 Uri 进行查询,返回一个 Cursor 。 insert(Uri url, Content

22、Values values ):将一组数据插入到 Uri 指定的地方。 update ( Uri uri, ContentValues values, String where, String selectionArgs ):更新 Uri 指定位置的数据。 delete (Uri url, String where, String selectionArgs):删除指定 Uri 并且符合一定条件的数据。4.2 ContentResolver外界的程序通过 ContentResolver 接口可以访问 ContentProvider 提供的数 据,在 Activity 当中通过 getConte

23、ntResolver() 可以得到当前应用的 ContentResolver 实例。ContentResolver 提供的接口和 ContentProvider 中需要实现的接口对应, 主要有以下几个。query(Uri uri, String projection, String selection, String selectionArgs,String sortOrder ):通过 Uri 进行查询,返回一个 Cursor 。insert ( Uri url, ContentValues values ):将一组数据插入到 Uri 指 定的地方。update (Uri uri, Cont

24、entValues values, String where, String selectionArgs ):更新 Uri 指定位置的数据。delete (Uri url, String where, String selectionArgs):删除指定 Uri 并且符合一定条件的数据。4.3 ContentObserver在注册,翻译成中文就是内容观察者,目的是观察 (捕捉)特定 Uri 引起的数 据库的变化,继而做一些相应的处理。 ContentObserver 一般和系统或第三 方程序提供的 Provider 一起使用,这些 Provider 一般情况下会有一个 Uri , 然后 Con

25、tentObserver 就去监听这些 Uri 数据的变化,然后做出相应的处理。4.4 ContentProvider 和 ContentResolver 中用到的 Uri在 ContentProvider 和 ContentResolver 当中用到了 Uri 的形式通常有两种, 一种是指定全部数据,另一种是指定某个 ID 的数据。我们看下面的例子。 content:/contacts/people/这个 Uri 指定的就是全部的联系人数据。 content:/contacts/people/1 这个 Uri 指定的是 ID 为 1 的联系人的 数据。在上边两个类中用到的 Uri 一般由 3

26、 部分组成。 第一部分是方案:content:这部分永远不变 第二部分是授权:contacts第二部分是路径:people/,people/1(如果没有指定ID,那么表示返回全部)。由于URI通常比较长,而且有时候容易出错,且难以理解。所以,在An droid 当中定义了一些辅助类, 并且定义了一些常量来代替这些长字符串的使用, 例如 下边的代码:Contacts.People.CONTENT_URI (联系人的 URI)。在我们的实例 MyProvider 中是如下定义的:public static final String AUTHORITY=com.teleca.PeopleProvid

27、er;public static final String PATH_SINGLE=people/#;public static final String PATH_MULTIPLE=people;public static final Uri content_URI=Uri.parse(content:/+AUTHORITY+/+PATH_MULTIPLE);5 Service 如何向 Activity 传递数据一个 Android 程序可以由多个 Activity 和 Servier 组成,在这些程序组件 之间传递数据的方法有以下几种,每种方法都有其特定的使用途径。5.1 原始数据类型在

28、Activity/Servier 之间 传递临时性的原始数据 ,可以使用 Intent 的 putExtras 方法来传递数据。若传递的数据需要 长久保存 ,则使用 SharedPreference 类来完成。5.2 传递对象当在 Activity/Servier 之间传递不需要长久保存的对象时,可以使用以下 几种途径:( 1 )通过 Application 类,每个 Android 应用程序都有一个 Application 类。当你在程序的 AndroidManifest.xml 中给 Application 设定一个名字时, 你 的程序中就必须有一个 Application 的子类。这个

29、Application 子类会被 Android 自动实例化,并且是一个全局性的类,它的生命周期和程序的生命周期 相同,你可以把一些全局性的对象保存在 Application 类中。 Application 类可 以通过 getApplication() 获得。(2)通过 HashMap of WeakReferences传递对象。当一个 Activity 需要向 另外一个 Activity 传递对象时,可以使用一个关键字把对象存在一个 HashMap 中,并把这个关键字通过In ternt 的Extras发给目标Activity ,目标Activity 接到该关键字后使用该关键字把对象从 H

30、ashMap中取出。5.3 在 Activity/Service 之间传递需要长久保存的对象时,可以使用以下的方式1. Application Preferences2. Files3. contentProviders4. SQLite DB6 AsyncTask6.1 底层处理底层使用本地线程池机制:1. 核心线程数:线程池中保存的线程数,包括空闲线程,默认为 5 个2. 线程池中允许的最大线程数,固定为 128 个+10个阻塞线程3. 当线程数大于核心线程数时,如果线程池中中线程数大于核心线程数 5 超过一秒事,终止多余的线程,保留五个核心线程数。4. 执行前用于保持任务的队列,此队列仅

31、保持 execute 方法提交的 Runnable 任务,固定容量为 105. 执行程序创建新线程时使用的工厂6.2 AsyncTask 介绍Android 的 AsyncTask 比 Handler 更轻量级一些(只是代码上轻量一些,而 实际上要比 handler 更耗资源),适用于简单的异步处理。首先明确An droid之所以有Han dler和Asy ncTask,都是为了不阻塞主线程 (UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的。An droid为了降低这个开发难度,提供了 Asy ncTask。Asy ncTask就是一个圭寸 装过的后台任务类,顾名思义就是

32、异步任务。AsyncTask 直接继承于 Object 类,位置为 android.os.AsyncTask 。要使用 AsyncTask工作我们要提供三个泛型参数,并重载几个方法(至少重载一个)。AsyncTask 定义了三种泛型类型 Params, Progress 和 Result 。Params启动任务执行的输入参数,比如HTTP青求的URLProgress 后台任务执行的百分比。Result 后台执行任务最终返回的结果,比如 String 。使用过 AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个 方法:doInBackground(Params)后台执行,比较耗

33、时的操作都可以放在这里。 注意这里不能直接操作 UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress )来更新任务的进度。onPostExecute(Result) 相当于 Handler 处理 UI 的方式,在这里面可以使 用在 doInBackground 得到的结果处理操作 UI。 此方法在主线程执行,任务执 行的结果作为此方法的参数返回有必要的话你还得重写以下这三个方法,但不是必须的: onProgressUpdate(Progress ) 可以使用进度条增加用户体验度。 此方 法在主线程执行,用于显示任

34、务执行的进度。onPreExecute() 这里是最终用户调用 Excute 时的接口,当任务执行之前开 始调用此方法,可以在这里显示进度对话框。onCancelled() 用户调用取消时,要做的操作 使用AsyncTask类,以下是几条必须遵守的准则:Task的实例必须在 UI thread 中创建;execute 方法必须在 UI thread 中调用;不要手动的调用 onPreExecute(), onPostExecute(Result) , doInBackground(Params.), onProgressUpdate(Progress.)这几个方法;该 task 只能被执行一次

35、,否则多次调用时将会出现异常;6.3 AsyncTask 实现的原理和适用的优缺点Asyn cTask,是an droid提供的轻量级的异步类,可以直接继承 Asy ncTask,在 类中实现异步操作 ,并提供接口反馈当前异步执行的程度 (可以通过接口实现 UI 进度更新 ), 最后反馈执行的结果给 UI 主线程.使用的优点 :简单 , 快捷过程可控使用的缺点 :在使用多个异步操作和并需要进行 Ui 变更时 , 就变得复杂起来 .7 Handler7.1 Handler 异步实现的原理和适用的优缺点1. Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 Messa

36、geQueue消息队列)。2. Handler: 你可以构造 Handler 对象来与 Looper 沟通,以便 push 新消息 到 MessageQueuei;或者接收 Looper 从 Message Queue取出)所送来的 消息。3. Message Queue消息队列):用来存放线程放入的消息。4. 线程: UIthread 通常就是 main thread ,而 Android 启动程序时会替它建立一个 MessageQueue在 Handler 异步实现时 , 涉及到 Handler, Looper, Message, MessageQueue 四个对象,实现异步的流程是主线程

37、启动 Thread (子线程)运行并生成Message 放至U MessageQueueLooper 从 MessageQueue获取 Message并传递给 Handler, Handler逐个获取Looper中的Message并进行UI变更。使用的优点:结构清晰,功能定义明确 对于多个后台任务时,简单,清晰 使用的缺点:在单个后台异步处理时,显得代码过多,结构过于复杂(相对性)7.2 Handler 介绍Handler 主要接受子线程发送的数据 , 并用此数据配合主线程更新 UI. 当应用程序启动时, Android 首先会开启一个主线程 , 主线程为管理界面中 的 UI 控件,进行事件分

38、发 , 更新 UI 只能在主线程中更新,子线程中操作是危险 的。这个时候, Handler 就需要出来解决这个复杂的问题。由于 Handler 运行在 主线程中(UI线程中),它与子线程可以通过Message对象来传递数据,这个时候, Handler 就承担着接受子线程传 过 来的 ( 子 线 程用 sedMessage() 方法传 递)Message对象(里面包含数据),把这些消息放入主线程队列中,配合主线程 进行更新 UI。7.3 Handler 的特点Handler可以分发Message对象和Runnable对象到主线程中,每个Handler 实例, 都会绑定至创建他的线程中 ,它有两个

39、作用 :(1) 安排消息或 Runnable 在某个主线程中某个地方执行(2) 安排一个动作在不同的线程中执行Handler 中分发消息的一些方法post(Runnable) postAtTime(Runnable,long) postDelayed(Runnable long) sendEmptyMessage(int) sendMessage(Message) sendMessageAtTime(Message,long) sendMessageDelayed(Message,long)以上 post 类方法允许你排列一个 Runnable 对象至主线程队列中 , sendMessage类

40、方法,允许你安排一个带数据的 Message对象到队列中,等待更新.7.4 综上所述数据简单使用AsyncTask: 实现代码简单,数据量多且复杂使用handler+thread : 相比较 AsyncTask 来说能更好的利用系统资源且高效8 ListView8.1 ListView 优化8.1.1 简介在 android 开发中 Listview 是一个很重要的组件,它以列表的形式根据数 据的长自适应展示具体内容 , 用户可以自由的定义 listview 每一列的布局,但当 listview 有大量的数据需要加载的时候,会占据大量内存,影响性能,这时候 就需要按需填充并重新使用 view

41、来减少对象的创建。ListView 加 载 数 据 都 是 在 public View getView(int position, View convertView, ViewGroup parent) 方法中进行的 ( 要自定义 listview 都需要重写 listadapter: 如 BaseAdapter , SimpleAdapter,CursorAdapter 的 等的 getvView 方法 ), 优化 listview 的加载速度就要让 convertView 匹配列表类型, 并最大程度上的重新使用 convertView 。8.1.2 getview 的加载方法一般有以下三种

42、种方式:1. 最慢的加载方式是每一次都重新定义一个 View 载入布局,再加载数据2. 正 确 的 加 载 方 式 是 当 convertView 不 为 空 的 时 候 直 接 重 新 使 用 convertView 从而减少了很多不必要的 View 的创建,然后加载数据3. 最快的方式是定义一个 ViewHolder ,将 convetView 的 tag 设置为 ViewHolder, 不为空时重新使用即可8.1.3 补充当处理一些耗时的资源加载的时候需要做到以下几点, 以使你的加载更快更平滑:1. 适配器在界面主线程中进行修改2. 可以在任何地方获取数据但应该在另外一个地方请求数据3.

43、 在主界面的线程中提交适配器的变化并调用 notifyDataSetChanged() 方法8.2 ListView 的图文混合显示8.2.1 异步加载图片基本思想:1. 先从内存缓存中获取图片显示(内存缓冲)2. 获取不到的话从SD卡里获取(SD卡缓冲)3. 都获取不到的话从网络下载图片并保存到 SD 卡同时加入内存并显示(视 情况看是否要显示)8.2.2 具体优化优化一:先从内存中加载,没有则开启线程从SD卡或网络中获取,这里注意从SD卡获取图片是放在子线程里执行的,否则快速滑屏的话会不够流畅。优化二:在adapter里新建一个busy变量,表示listview 是否处于滑动状 态,如果是

44、滑动状态则仅从内存中获取图片, 没有的话无需再开启线程去外存或 网络获取图片。优化三 :利用线程池在从网络获取图片时,先是将其保存到 sd 卡,然后再 加载到内存, 这么做的好处是在加载到内存时可以做个压缩处理, 以减少图片所 占内存资料与源码实现(见附件)8.2.3 关于图片错位的处理图片错位问题的本质源于我们的 listview 使用了缓存 convertView ,假设一 种场景,一个 listview 一屏显示九个 item ,那么在拉出第十个 item 的时候, 事实上该 item 是重复使用了第一个 item ,也就是说在第一个 item 从网络中下 载图片并最终要显示的时候其实该

45、 item 已经不在当前显示区域内了,此时显示 的后果将是在可能在第十个 item 上输出图像,这就导致了图片错位的问题。所 以解决 之道 在于 可见 则显示 ,不 可见 则不 显示。 在 ImageLoader 里 有个 imageViews的map对象,就是用于保存当前显示区域图像对应的url集,在显示前判断处理一下即可。9 JNI9.1 快速智能开发步骤1. 配置NDK目录结构(只需一次)2. 添加本地支持:右键选中工程, Android Tools Add native support3. 将 cpp 代码改成 c 代码,注意 Android.mk 文件也要修改, 刷新工程, 删 除

46、obj 目录4. 声明本地方法,实现对应c代码实现:Javah+全类名 生成本地方法标头 文件,把头文件剪切到 jni 目录下, c 代码引用头文件,实现头文件里 的方法。5. 实现对应的 c 代码6. 交叉编译,一锤子敲下去7. 使用静态代码块,引用库函数,调用方法9.2 开发中常见的 JNI 问题9.2.1 错误一10-31 06:42:33.645: E/AndroidRuntime(805): java.lang.UnsatisfiedLinkError:Native method not found:com.example.ndk2.MainActivity.hello_From_C

47、:()Ljava/lang/String;1. 引入的函数库名字不对 , 或者没有引入2. java 方法和 c 方法不对应3. 部署的平台有问题9.2.2 错误二当前工程报错 , 但是没有任何文件有错误 , 有可能 Android.mk 有问题在 Android.mk 文件中 不要用到全角空格或者回车9.2.3 错误 3在 C 代码中有编译时异常 , 在控制台上会提示9.2.4 错误 410-31 06:53:23.165: A/libc(2075): Fatal signal 11 (SIGSEGV) at 0x476a415c(code=2), thread 2075 (om.examp

48、le.ndk2)下面打印一大堆 debug 信息C 代码中 有运行时异常9.3 应用场景1. 输出日志2. 收集用户反馈信息3. 用户登录4. 加密算法5. 电商数据加密10 静默安装10.1 方式一:定制 ROMGoogle的安全策略要求任何应用应该提示 APK安装包的权限,对于一些内置 特定厂商应用,可以跳过安装过程的信息加快安装,或者运营商强制安装。10.2 方式二:查看系统源码10.2.1 基本原理在窗口中点击一个APK时,触发单击事件,Packagelnstaller 接收系统服务 PackageManagerService 传来的 intent 信息,传来的 Intent 信息中有

49、 APK的一 些参数。实现的关键是区分一般 APK和特定APK通过传给 PackageManagerService 的 intent 中 添加特 别的 参数, PackageInstaller 接收后进行判断,进行特别的隐藏安装流程。这个实现只能 通过程序调用的方式安装。安装过程的信息窗口在 PackageInstallActivity.java 中实现的。安装过程 的信息窗口有 4 个:需要实现一个 PakkageInstallActivityHide.JAVA 的文件, 去掉下面的 dialog 和窗口安装权限确认窗口: installPermissionConfirm安装进度条 :ins

50、tallProgress安装结果窗口 :installResult安装错误提示对话框10.2.2 具体实现(方法一)1. 在 Androidmainfest.xml 声明一个特定的 intent : ent.action.VIEW.HIDE ,由 PackageInstallActivityHide.java来接受业)51更先的* hbdrcid: thtne la ndroi d: scjfle/Tti ent+Ho1b.ilDgWhaEl改砺sr.iz ? l d r L*g el- ; i ri把x: z : tairsiJiot/TTkiicQflWfcc aLa

51、:吓“主S6的显待il在毎一htivitr 呻,叢窖正常装的二片阿寻1 J !T北.akka se I ns : a 11 Ac ti v i :yElde的.4懸巳能呈:j.HaDisplay1 M能呈德卜.设自體-12.实现 PakkagelnstallActivityHide.java , UninstallerActivityHide.java只需把 PakkageInstallActivity.java修改去掉 dialog 和对话框。3. 安装程序调用者发一个上面定义的in te nt即可。如下例子,静默安装/sdcard/hello.apk4. 卸载的方法类似。5. 注意,这个方

52、法需要Package In stall这个apk必须与系统一起编译。这个apk 在/system/app/ 目录下面;ent.action.VIEW.HIDE这个静默安装的接口需要开放给第三方。10.2.3具体实现(方法二)1. 从模拟器 Systemframework 目录下提取 framework.jar2. 将framework.jar 后缀名改为zip,解压后提取其中的classes.dex文件3. 用 dex2jar 工具将 classes.dex 转成 classes.dex.dex2jar.jar(注意新版本的 dex2jar 工具无法转换 Android2

53、.2的framework ,建议使用dex2jar--SNAPSHOT,该工具可以从google官方站上下载到)4. 将 classes.dex.dex2jar.jar 改名为 classes.dex.dex2jar.zip解压取出an droid/co nte nt/pm/目 录 下 的PackageMa nager.class,IPackageInstallObserver.class, IPackageDeleteObserver.class 及相关的几个class文件备用5. 找至U android-sdk 目录下的 android.jar,改名为 android.zip

54、(注意改名前先备份一下),解压后将步骤4中取得的class文件覆盖到an droid对应的 目录下,6. 这个时候你的android.jar 已经是一个更新过的 SDK了,重新打开eclipse 工程,你已经可以调用方法:voidan droid.co nten t.pm.PackageMa nager.i nstallPackage(UripackageURI, IPackage In stallObserver observer, i nt flags, String in stallerPackageName)11 Android中数据的存储方式11.1方式1. Shared Prefe

55、rences :主要用于保存程序的系统配置信息。用来存储 “ key- values paires ”。一般用于保存程序启动时设定的信息,以便在 程序下一次启动时继续保留前一次设定的信息。2. xml3. Files :用文件的形式保存信息。 可以通过对文件的读写来获取或保存相 关信息。4. SQLite :用数据库的形式保存信息。 SQLite 是一个开源的数据库 系统。5. Network:将数据保存于网络。11.2 区 别1. Shared Preferences :Android 提供用来存储一些简单的配置信息的一种机制,例如,一些默 认欢迎语、登录的用户名和密码等。其以键值对的方式存储,SharedPreferences是以XML的格式以文件的方式自动保存的,在DDMS中的 File Explorer 中展开到 /data/data/shared_prefs 下, 以上面这个为例,可以看到一个叫做 SETTING_Infos.xml 的文件2. Files在 Android 中,其提供了 openFileInput 和 openFileOuput 方法读取 设备上的文件,下面看个例子代码,具体如下所示:String FILE_NAME = tempfile.tmp; / 确定要操作文件的文件名 FileOutputStreamfos = openFile

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论