android--多线程,android多线程

线程的基本用法:

android多线程编程其实并不比java多线程特殊,基本都是使用相同的语法,比如说,定义一个线程只需要新建一个类继承自Thread,然后重写父类的run()方法,并在里面编写耗时的逻辑即可,

public classMyThread extends Thread {

@Overridepublic voidrun() {//处理具体的逻辑

super.run();

}

}

如何启动这个线程,其实也很简单,只需要new出MyThread的实例,然后调用它的start()方法,这样run()方法中的代码就会在子线程当中运行了。

new MyThread().start();

使用继承的方式耦合性有点高,更多的时候我们都会选择使用Runnable接口的方式定义一个线程

public classMyThread implements Runnable{

@Overridepublic voidrun() {//处理具体的逻辑

}

}

如果使用了这种写法,启动线程的方法也需要进行相应的改变,

MyThread mythread=new MyThread();

new Thread(mythread).start();

当然如果不想专门再定义一个类去实现runnable接口,也可以使用匿名累的方式,如下所示:

Thread thread= new Thread(newRunnable() {

@Overridepublic voidrun() {//具体处理逻辑

}

}).start();

再子线程中更新UI

和许多其他GUI库一样,安卓的UI也是线程不安全的,也就是说,如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。

下面我们来看一个例子:

android:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/change_text"android:text="send request"/>

android:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/text1"android:text="hello world"android:textSize="20sp"

/>

public classMainActivity extends Activity implements View.OnClickListener {privateTextView textView;privateButton changeText;

@Overrideprotected voidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

textView=(TextView)findViewById(R.id.text1);

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

changeText.setOnClickListener(this);

}

@Overridepublic voidonClick(View v) {switch(v.getId()){caseR.id.change_text:new Thread(newRunnable() {

@Overridepublic voidrun() {

textView.setText("Nice to neet you");

}

}).start();break;default:break;

}

}

运行的时候会出现如下图所示的情况:

a8d709b6bf0ac986be7d8fe87352a72c.png

由此正式了安卓确实是不允许自线程中运行UI操作,但是有时候我们必须在子线程里面去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件,

安卓提供了一套异步消息处理机制完美的解决了在子线程中运行UI操作。

首先我们先来看一下这个解决的代码

public classMainActivity extends Activity implements View.OnClickListener {privateTextView textView;privateButton changeText;public static final int UPDATE_TEXT=1;private Handler handler=newHandler() {

@Overridepublic voidclose() {

}

@Overridepublic voidflush() {

}

@Overridepublic voidpublish(LogRecord record) {

}public voidhandleMessage(Message msg){switch(msg.what){caseUPDATE_TEXT:

textView.setText("Nice to meet you");break;default:break;

}

}

};

@Overrideprotected voidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

textView=(TextView)findViewById(R.id.text1);

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

changeText.setOnClickListener(this);

}

@Overridepublic voidonClick(View v) {switch(v.getId()){caseR.id.change_text:new Thread(newRunnable() {

@Overridepublic voidrun() {

Message message=newMessage();

message.what=UPDATE_TEXT;

handler.sendMessage(message);

}

}).start();break;default:break;

}

}

我们来解析异步消息处理机制:

安卓中的异步消息处理主要由四部分组成,Message,Handler,MessageQueue和Looper。

1 Message

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

2 Handler

Handler故名思义也就是处理者的意思,它主要是用于发送和处理消息的,发送消息一般是使用Handler的sendmessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler地handleMessage()方法中,

3MessageQueue

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

4 Looper

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

首先需要在主线成中创建一个Handler对象,并重写handleMessage()方法,然后子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去,之后这条消息会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,最后奋发回Handler的handleMessage()方法中,由于Handle是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线成中运行,于是我们在这里就可以安心的运行UI操作,整个异步消息处理的核心思想就是这样。5363eeed835069f2966181ebccf2d31e.png

为了更加方便我们在自线程中对UI进行操作,android还提供了另外的一些好用的工具,AsyncTask就是其中之一,借助AsyncTask,即使你对异步消息处理机制完全不了解,也可以十分简单的从子线程切换的主线程,AsyncTask背后的实现原理也是基于异步消息处理机制的。

由于AsyncTask是一个抽象类,所以如果我们想要使用它,就必须创建一个子类去继承它,在继承AsyncTask类指定三个范性参数,这三个参数的用途如下:

1 params

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

2progress

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

3 result

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

我们还需要自定义一些方法才能完成对任务的定制。

1 onPreExecute()

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

2 doInBackground(Params...)

这个方法中所有代码都会在自线程中运行,我们应该在这里去处理所有的耗时任务,任务一旦完成就可以通过return语句来将任务的执行结果返回,如果AsyncTask的读三个泛型参数指定的是void,就可以不返回任务执行结果,注意,在这个方法中是不可以进行ui操作的,如果要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。

3 onProgressUpdate(Progress...)

当在后台任务中调用了publishprogress(progress...)方法后,这个方法就会很快被调用,方法中携带的参数就是在后台任务传递过来的,在这个方法中可以对UI进行操作。利用参数中的数值就可以对界面元素进行相应的更新。

4 onPostExecute(Result)

当后台任务执行完毕并通过return语句进行返回时,这个方法就很快会被调用,返回的数据会作为位参数传递到此方法中,可以利用返回的数据来进行一些UI操作,比如说提醒任务执行的结果以及关闭掉进度条对话框。

如果要启动的话只需要调用其execute()方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值