android多线程编程

Thread, Handler,runOnUIThread 的使用

1、Thread的使用

  1.         UI是在主线程中运行的。后台服务如果直接运行在主线程,可能会导致阻塞等,因此将服务由子线程来实现。

        Android可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口:

        前者只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是Java中一个类只能继承一个父类,这是这种方式的局限性,后者只需要实现一个接口而已,Java中可以实现多个接口。

    2.        由于UI是线程不安全的(判断是否安全是根据当它在多个线程同时访问它时,程序执行后结果是否保持一致),要将其在主线程中运行。当要更改UI时,可以开辟一个子线程和Handler(或者runOnUIThread)实现。

2、Handler

        Handler是更新线程的一种方式。使用Handler更新UI线程的过程:在主线程中创建Handler实例,并重写handleMessage方法。在子线程中创建Message实例,并用sendMessage方法发送。这样,就将子线程中UI传递给主线程。

3、runOnUIThread

        runOnUIThread也是更新线程的一种方式。它的使用方法:Test.activity.this.runOnUIThread(new runnable()); runOnUIThread的实现原理是判断runnable实例是否是在主线程,如果不是则调用post。

        

了解常见导致 ANR 的原因
AsyncTask

哪些任务不能放到 UI 主线程里执行?

1、了解常见导致 ANR 的原因

    在Android里,应用程序的响应性是由Activity Manager和WindowManager系统服务监视的 。当它监测到以下情况中的一个时,Android就会针对特定的应用程序显示ANR:

1.在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸)
2.BroadcastReceiver在10秒内没有执行完毕

造成以上两点的原因有很多,比如在主线程中做了非常耗时的操作,比如说是下载,io异常等。

   

    潜在的耗时操作,例如网络或数据库操作,或者高耗时的计算如改变位图尺寸,应该在子线程里(或者以数据库操作为例,通过异步请求的方式)来完成。然而,不是说你的主线程阻塞在那里等待子线程的完成——也不是调用 Thread.wait()或是Thread.sleep()。替代的方法是,主线程应该为子线程提供一个Handler,以便完成时能够提交给主线程。以这种方式设计你的应用程序,将能保证你的主线程保持对输入的响应性并能避免由于5秒输入事件的超时引发的ANR对话框。

第二:如何避免ANR?

1、运行在主线程里的任何方法都尽可能少做事情。特别是,Activity应该在它的关键生命周期方法(如onCreate()和onResume())里尽可能少的去做创建操作。(可以采用重新开启子线程的方式,然后使用Handler+Message的方式做一些操作,比如更新主线程中的ui等)

2、应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为 BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个 Service。(此处需要注意的是可以在广播接受者中启动Service,但是却不可以在Service中启动broadcasereciver,关于原因后续会有介绍,此处不是本文重点)

3、避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广 播时需要向用户展示什么,你应该使用Notification Manager来实现。

AsyncTask

AsyncTask定义了三种泛型类型 Params,Progress和Result。

  • Params 启动任务执行的输入参数,比如HTTP请求的URL。
  • Progress 后台任务执行的百分比。
  • Result 后台执行任务最终返回的结果,比如String。

使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:

  • doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
  • onPostExecute(Result)  相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回

有必要的话你还得重写以下这三个方法,但不是必须的:

  • onProgressUpdate(Progress…)   可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
  • onPreExecute()        这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
  • onCancelled()             用户调用取消时,要做的操作

使用AsyncTask类,以下是几条必须遵守的准则:

  • Task的实例必须在UI thread中创建;
  • execute方法必须在UI thread中调用;
  • 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
  • 该task只能被执行一次,否则多次调用时将会出现异常;

ADB调试

adb devices , 获取设备列表及设备状态

adb get-state , 获取设备的状态

设备的状态有 3 钟,device , offline , unknown

device:设备正常连接

offline:连接出现异常,设备无响应

unknown:没有连接设备

adb kill-server , adb start-server , 结束 adb 服务, 启动 adb 服务,通常两个命令一起用

adb logcat

adb bugreport , 打印dumpsys、dumpstate、logcat的输出,也是用于分析错误

adb install , 安装应用,覆盖安装是使用 -r 选项

adb uninstall , 卸载应用,后面跟的参数是应用的包名,请区别于 apk 文件名。-k 选项,卸载时保存数据和缓存目录

adb pull , 将 Android 设备上的文件或者文件夹复制到本地
 

例如复制 Sdcard 下的 pull.txt 文件到 D 盘:adb pull sdcard/pull.txt d:\

如果需要重命名为 rename.txt:adb pull sdcard/pull.txt d:\rename.txt

adb push , 推送本地文件至 Android 设备。例如推送 D 盘下的 push.txt 至 Sdcard:adb push d:\push.txt sdcard/

 

adb forward , 将 宿主机上的某个端口重定向到设备的某个端口:adb forward tcp:1314 tcp :8888

adb connect 远程连接 Android 设备:手机、PC处于相同的网络下,手机 root ,安装应用 adbWireless ,启动应用后点击界面中间的按钮,接着运行 adb connect 192.168.1.102 , 即可通过无线的方式连接手机,缺点是速度比较慢

在安装NDK时遇到的问题:在SDK Manager中SDK tools选项没有Cmake。解决方案:

猜你喜欢

转载自blog.csdn.net/murongxian_1/article/details/80657640