第一种方式:
class MyThread extends Thread{
public void run(){
// 写耗时操作代码
// Only the original thread that created a view hierarchy can touch its views.
// 如果子线程已经执行了耗时操作,那么就不能修改视图的属性了;视图的属性只能在UI线程去修改
}
}
MyThread myThead = new MyThread();
myThread.start();
第二种方式:
class MyRunnable implements Runnable {
@Override
public void run() {
try {
Thread.sleep(3000);
String result = "runnable 345345";
Log.i("runnable", result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
第三种方式:(常见、推荐)
new Thread(new Runnable() {
@Override
public void run() {
// 耗时任务
try {
Thread.sleep(3000);
String result = "匿名线程";
Log.i("匿名线程",result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
3、Handler
/**
* 从服务器接收到用户的昵称,并将昵称设置在textview对应的text属性上
*
* 连接服务器的功能,是属于耗时任务,所以必须放在子线程
*
* 子线程中是没有办法修改页面,借助Handler给主线程传递消息
*
* 主线程接收到消息后,开始执行修改UI
*/
public class MainActivity2 extends AppCompatActivity {
// 声明容器
private TextView tv1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
// 根据ID获取页面控件
tv1 = findViewById(R.id.tv1);
// 模拟一个连接服务器的过程
new Thread(new Runnable() {
@Override
public void run() {
try {
// 本意是想表达 连接服务器的耗时操作
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 假如从服务器获取到昵称为:炸炸最炸
String result = "炸炸最炸";
// 将昵称给textview设置上,在子线程中更新UI,是不允许的,必须使用handler将消息传递回去
Message message = new Message();
message.what = 1;
message.obj = result;
handler.sendMessage(message);
}
}).start();
}
private Handler handler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
String result = (String) msg.obj;
tv1.setText(result);
}
}
};
}
4 进度条
public class MainActivity3 extends AppCompatActivity {
private ProgressBar progressBar;
int status = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
progressBar = findViewById(R.id.progressBar);
new Thread(new Runnable() {
@Override
public void run() {
// 循环对status进行值得修改
while (status < 100) {
try {
Thread.sleep(100);
status++;
handler.sendEmptyMessage(0x111);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
if (msg.what == 0x111) {
progressBar.setProgress(status);
}
}
};
}
5.Service解决ANR
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("serivce","服务已开启");
new Thread(new Runnable() {
@Override
public void run() {
long endtime = System.currentTimeMillis() + 20 * 1000; // 获取当前系统再加上20秒
while(System.currentTimeMillis() < endtime) {
synchronized (this){
try {
wait(endtime - System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
结论:
Service不会自动开启线程,也不会自动停止线程
6 IntentService
如何创建一个IntentService
new Class-> MyIntentService ->继承IntentService->实现onHandleIntent 和 构造方法
在AndroidManifest.xml中注册,注册时发现报错,报错的原因是没有无参的构造方法,解决办法:创建无参的构造方法
7 handlerThread
handlerThread还是一个线程,带了Looper的线程
总结:
Activity 耗时操作 子线程, handler
Service Service不会自动开启线程,也不会自动停止线程
IntentService 自动开启线程,并在执行完毕后,关闭线程