android代码里 写线程,Android第一行代码(十二)多线程编程

线程的基本用法:

定义一个线程只需要新建一个类继承自Thread,然后重新父类的run()方法,并在里面编写耗时逻辑即可

class MyThread extends Thread{

@Override

public void run(){

//处理具体的逻辑

}

}

然后启用这个线程,只需要调用该类的start方法即可:

new MyThread().start()

但是使用继承的方式耦合性有点高,更多时候选择使用实现Runable接口的方式来定义一个线程

class MyThread implemens Runnable {

@Override

public void run(){

//处理具体逻辑

}

}

使用这种写法,启动线程是:

MyThread myThread = new MyThread();

new Thread(myThread).start();

Android是不允许在子线程中进行UI操作的,我们可以利用Android提供的异步消息机制,来解决在子线程中进行UI操作的问题。

public class MainActivity extends AppCompatActivity {

public static final int UPDATE_TEXT = 1;

private TextView text;

//消息接收处理的handler

private Handler handler = new Handler(){

@Override

public void handleMessage(Message msg) {

switch (msg.what){

case UPDATE_TEXT:

Log.d("MainActivity","test");

//在这里进行UI操作

Log.d("MainActivity",""+msg.arg1);

text.setText("Nice to meet you");

break;

default:

break;

}

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

text = (TextView)findViewById(R.id.text);

Button changeText = (Button)findViewById(R.id.change_text);

changeText.setOnClickListener(new View.OnClickListener(){

@Override

public void onClick(View v) {

new Thread(new Runnable() {

@Override

public void run() {

//在子线程里发送更新文字的message

Message message = new Message();

message.what = UPDATE_TEXT;

message.arg1 = 1;

handler.sendMessage(message);

}

}).start();

}

});

}

}

解析异步消息处理机制:

Android的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper

Message

Message 是在线程之间传递的消息,可在内部携带少量的信息,用于不同线程之间交换数据。

有what、arg1、arg2来携带一些整形数据,使用obj字段携带一个Object对象

Handler

Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息。

发送消息一般使用Handler的sendMessage()方法;处理消息使用Handler的 handleMessage()方法

MessageQueue

MessageQueue是消息队列的意思,它主要是用于存放所有通过Handler发送的消息。这部分消息会一直存放在消息队列中,等待被处理。每个线程中只会有一个Message对象。

Looper

Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无线循环当中,然后每当发现MessageQueue中存在一条消息,就会将它取出,并传递到Handler的handleMessage()方法当中

9825a72b4cb6

异步消息处理流程.png

使用AsyncTask

由于AsyncTask是一个抽象类,所以要使用它,就必须创建一个子类去继承它。在继承时,可以为AsyncTask类指定3个泛型参数,这3个参数的用途如下:

Params

在执行AsyncTask时需要传入的参数,可用于在后台任务中使用

Progress

后台任务执行时,如果需要在界面上显示当前进度,则使用这里指定的泛型作为进度单位

Result

当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型

使用AsyncTask还经常需要重写以下4个方法:

onPreExecute()

在后台任务开始执行之前调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框

doInBackground(Params...)

这个方法中所有的代码都在子线程执行,应该在这里处理所有的耗时任务。在这个方法中是不能进行UI操作的,只能调用publishProgress(Progress...)方法将数值传递出去,并触发 onProgressUpdate(Progress...)方法

onProgressUpdate(Progress...)

当在后台任务中调用了publishProgress(Progress...)方法后,onProgressUpdate(Progress...)方法就会很快被调用,该方法中携带的参数就是在后台任务中传递过来的,在这个方法中可以对UI进行操作。

onPostExecute(Result)

后台任务执行完毕并通过return语句进行返回时,这个方法就很快被调用,返回的数据就会作为参数传递到此方法之中,可以利用返回的数据来进行一些UI操作。

public class DownloadTask extends AsyncTask {

ProgressDialog progressDialog = new ProgressDialog();

@Override

protected void onPreExecute() {

progressDialog.show(); //显示进度对话框

}

@Override

protected Boolean doInBackground(Void... params) {

try {

while (true) {

int downloadPercent = doDownload();

//此处调用publishProgress()方法,会触发 onProgressUpdate()方法

publishProgress(downloadPercent);

if (downloadPercent >= 100) {

break;

}

}

}catch(Exception e){

return false;

}

return true;

}

}

@Override

protected void onProgressUpdate(Integer... values) {

//在这里进行UI操作,更新进度条

progressDialog.setMessage("Downloaded " + values[0] + "%");

}

@Override

protected void onPostExecute(Boolean result) {

progressDialog.dismiss();

//在这里提示下载结果

if(result) {

Toast.makeText(context, "Download successed", Toast.LENGTH_SHORT).show();

}else {

Toast.makeText(context, "Download faild", Toast.LENGTH_SHORT).show();

}

}

}

启用这个任务,只需要

new DownloadTask().execute();

简单来说,使用AsyncTask的诀窍就是,在onPreExecute()方法中进行初始化工作,在doInBackground()方法中执行具体的耗时任务,在onProgressUpdate()方法中进行UI操作,在onPostExecute()方法中执行一些任务的收尾工作。

而调用publishProgress()方法,能够将数据从后台传递到主线程,触发onProgressUpdate(Progress...)方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值