Android多线程编译的问题一直都是HR青睐的面试题,因为多线程编译在Android开发过程中占有一定的地位。如果我们把一个耗时操作放在主线程中,就会导致主线程被阻塞,影响软件的正常使用。所以我们一般会把一个耗时任务放在一个子线程中,那如果是多个耗时任务呢?所以就有了多线程编译。
Android中是怎么创建一个线程的呢?办法有三个:
1.新建一个类继承自Thread,然后重写父类的run()方法,然后把耗时逻辑编写在里面,如:
class MyThread extends Thread{ @Override public void run() { super.run(); //处理逻辑写这里 } }
然后我们通过new一个MyThread的实例,调用start()方法:new MyThread().start();
2.我们还可以通过去实现Runnable接口的方法去定义一个线程,如:
class MyThread implements Runnable{ @Override public void run() { //处理逻辑写这里 } }
因为是这个方法是实现了接口,所以启动线程的方法有所调整:
MyThread mythread = new MyThread()
new Thread(mythread).start();
3.最常见的方法就是使用匿名类去创建一个线程,如:
new Thread(new Runnable() { @Override public void run() { //处理逻辑写这里 } }).start();
通过上面的学习你已经对线程的创建和使用有了一定的了解,那么你是否知道在Android中,UI的更新是不能在子线程中进行的。Android的UI线程是不安全的,我们要更新应用程序的UI元素,必须在主线程中进行,否侧就会出现异常。那么我们怎么样才能在子线程中进行UI操作呢?

(此图是百度找的,如若有侵权请联系版主删除图片)
1.Message
2.Handler
3.MessageQueue
MessageQueue主要是用于存放所有通过Handler发送的消息,它相当于一个消息队列。要记住的是每个线程只会有一个MessageQueue对象。
4.Looper
现在我们应该对这四个部分有了初步的了解了,现在我们来捋捋Android异步消息处理机制的整个流程。首先要在主线程当中创建一个Handler对象,并重写handlerMessage()方法。然后当子线程中有需要进行UI操作时,就要创建一个Message对象,并通过Handler对象的sendMessage()方法把这条消息发送出去。之后这调消息会存储在MessageQueue的队列中等待被处理,而Looper此时会一直尝试从MessageQueue中取出待处理的消息,最后分发回Handler的handlerMessage()方法中。但是由于Handler是在主线程中创建的,所以此时handlerMessage()方法中的代码也会在主线程中运行,这样就能达到了我们想要的效果,这就是异步消息处理的核心思想。弄懂了原理后我们在代码上实现一下看看效果是不是如我们所想,上个最简单的例子,我们做一个能通过点击按钮然后改变文本控件显示的内容的功能来试试。上代码图:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ final static int CHANGE_TEXT = 1;//先定义一个整型变量来表示更新TextView这个动作 private Button bt_change; private TextView tv_texr; Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case CHANGE_TEXT: tv_texr.setText("我变了");//接收到消息后改变textview里面的文本 } } };//创建Handler对象在主线程 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_change = (Button) findViewById(R.id.bt_change); tv_texr = (TextView)findViewById(R.id.tv_text); bt_change.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.bt_change: new Thread(new Runnable() { @Override public void run() { Message message = new Message();//实例化一个Message对象 message.what = CHANGE_TEXT;//通过what字段存储消息 handler.sendMessage(message);//使用handler对象的sendMessage方法把这条消息发送到handlerMessage方法中 } }).start();//通过创建一个匿名类的方式去创建一个子线程 break; } } }
上面代码的基本思路是:先定义一个整型变量CHANGE_TEXT,用于表示更新TextView的文本内容这个动作。然后实例化一个Handler对象,并重写handlerMessage()方法,对发送的Message的what字段进行处理,如果等于CHANGE_TEXT,就将TextView显示的文本内容进行相应的变化。那我们的Message是从哪来的呢?这里我实现了点击监听事件的接口,当我们点击bt_change这个按钮时,我们就以匿名类的方式创建一个子线程,并在子线程中实例化一个Message对象。之后我们把Message对象的what字段的值指向了CHANGE_TEXT,然后调用Handler的sendMessage()方法把这个消息发送出去。这样就完美的解决了在子线程中更新UI界面的功能了。
当然大家如果有兴趣的话,其实Android还提供了另外一个可以处理异步消息的工具——AsyncTask,你们可以去了解了解一下这个工具。它不需要你去深入了解异步消息处理机制,也可以在子线程切换到主线程。但是它其实实现的原理都一样,只是Android帮我们做好了封装,我们可以直接使用它而不需要懂其中的运行原理,我在这里就不详细介绍了。
转载的小伙伴请表明原创出处:原创链接
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211612.html原文链接:https://javaforall.net
