1.安卓的程序执行的入口UI主线程
所有的Android应用程序组件——包括Activity、Service和Broadcast Receiver,都运行在主线程.因此,任何组件中的耗时操作都将阻塞其它的组件,包括Service和可见的Activity.
使用后台线程,对于避免第2章中曾描述的“应用程序无响应ANR”对话框的情况是至关重要的.在Android中定义的无响应是指:Activity在5秒内不响应任何输入事件(例如一个按键事件)和Broadcast Receiver在10秒未完成onReceive的处理操作.
不仅仅是你要避免这种情况,甚至是你都不应该能遇到这种情况.为耗时的处理使用后台线程,包括文件操作、网络搜索、数据库交互和复杂的计算.
2.Thread普通线程
执行耗时操作,避免ANR操作。
3.HandlerThread (重点分析)
a.内部源码实现
b.经典的demo实现,卸载sd卡服务
一.主界面Activity实现
package com.example.testhanlerthread;
import java.lang.reflect.Method;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.os.storage.IMountService;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener{
public TextView textview;
public Button handlerThreadBTN;
HandlerThread handlerThread;
//作为全局变量进行消息的发放和接收到消息的处理
Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//打印UI线程的名称
System.out.println("onCreate CurrentThread = " + Thread.currentThread().getName());
setContentView(R.layout.activity_main);
textview = (TextView) findViewById(R.id.textView1);
handlerThreadBTN = (Button) findViewById(R.id.handlerThreadBtn);
handlerThreadBTN.setOnClickListener(this);
handlerThread = new HandlerThread("myHanler");
handlerThread.start();
//注意: 这里必须用到handler的这个构造器,因为需要把callback传进去
//从而使自己的HandlerThread的handlerMessage来替换掉Handler原生的handlerMessage,对注销的语句解释
//handler = new Handler(handlerThread.getLooper(), handlerThread);
handler = new Handler(handlerThread.getLooper()){
public void formatSdcard(){
//Phone path
//String sDStateString="/mnt/sdcard";
String sDStateString="/storage/sda1"; //ott path
Method method;
int a=-1;
try {
System.out.println("startformat");
method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);//利用反射得到ServiceManager类中的getService方法
IBinder binder = (IBinder) method.invoke(null, "mount");
IMountService iMountService = IMountService.Stub.asInterface(binder);
iMountService.unmountVolume(sDStateString, true,false);//卸载T卡
SystemClock.sleep(4000);
a=iMountService.formatVolume(sDStateString);
System.out.println(a);
if(a==0){
iMountService.mountVolume(sDStateString);
}
} catch (Exception e) {
System.out.println("输出异常信息="+e.getMessage());
e.printStackTrace();
}
}
@Override
public void handleMessage(Message msg) {
//格式化Sdcard卡服务
formatSdcard();
/*
//子线程执行体
System.out.println(" handleMessage CurrentThread = " + msg.what);
System.out.println(" handleMessage CurrentThread = " + msg.getTarget());
//打印线程的名称 和ID
System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());
System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getId());
//textview.setText("hahahahahhahahahah");注意这里是子线程更新UI组件是禁止的,注意HandlerThread
//不能用于UI更新
Toast.makeText(MainActivity.this, "haha",
Toast.LENGTH_LONG).show();
*/
}
};
}
@Override
public void onClick(View v) {
//点击按钮后来开启线程 ,线程触发指令,想MQ中投递消息
handler.sendEmptyMessage(1);
}
/*
private class MyHandlerThread extends HandlerThread implements Callback {
public MyHandlerThread(String name) {
super(name);
}
@Override
public boolean handleMessage(Message msg) {
System.out.println(" handleMessage CurrentThread = " + msg.what);
System.out.println(" handleMessage CurrentThread = " + msg.getTarget());
//打印线程的名称 和ID
System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());
System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getId());
return true;
}
*/
}
二.布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.testhanlerthread.MainActivity$PlaceholderFragment" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
<Button
android:id="@+id/handlerThreadBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginTop="99dp"
android:text="@string/startHandlerThread" />
</RelativeLayout>
三.配置文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.testhanlerthread"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS">
</permission>
<permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS">
</permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.testhanlerthread.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
四.引入的包
由于sd卡的卸载服务,我们采用了AIDL远端服务,因此我们应该导入包含此服务的android.jar的包,这里还利用了反射机制,进行hide服务的获取情况,因此本例子是一个非常典型的综合服务的情况。
4.异步任务类
5.两种线程以及异步任务类的区别